コード例 #1
0
        public static EcmaValue Wait(TypedArray array, EcmaValue index, EcmaValue value, EcmaValue timeout)
        {
            int  pos       = ValidateWaitableArrayAndIndex(array, index);
            bool isInt32   = array.ArrayKind == TypedArrayKind.Int32Array;
            long longValue = isInt32 ? value.ToInt32() : value.ToBigInt64().ToInt64();

            timeout = timeout.ToNumber();
            if (!RuntimeExecution.Current.CanSuspend)
            {
                throw new EcmaTypeErrorException("Atomics.wait cannot be called in this context");
            }
            bool comparandEquals, result;
            int  milliseconds        = timeout.IsNaN || timeout > Int32.MaxValue ? -1 : timeout < 0 ? 0 : timeout.ToInt32();
            SharedArrayBuffer buffer = (SharedArrayBuffer)array.Buffer;

            if (isInt32)
            {
                result = buffer.Wait(array.GetByteOffset(pos), (int)longValue, milliseconds, out comparandEquals);
            }
            else
            {
                result = buffer.Wait(array.GetByteOffset(pos), longValue, milliseconds, out comparandEquals);
            }
            return(result ? "ok" : comparandEquals ? "timed-out" : "not-equal");
        }
コード例 #2
0
        public static EcmaValue Notify(TypedArray array, EcmaValue index, EcmaValue count)
        {
            int pos = ValidateWaitableArrayAndIndex(array, index);

            count = count == default ? Int32.MaxValue : count.ToNumber();
            int countValue           = count.IsNaN || count <= 0 ? 0 : count > Int32.MaxValue ? Int32.MaxValue : count.ToInt32();
            SharedArrayBuffer buffer = (SharedArrayBuffer)array.Buffer;

            return(buffer.Notify(array.GetByteOffset(pos), countValue));
        }
コード例 #3
0
        private static EcmaValue DoAtomicOperation(TypedArray array, EcmaValue index, Operation operation, EcmaValue value, EcmaValue replacement)
        {
            int i = ValidateArrayAndIndex(array, index);

            value       = value.ToNumber();
            replacement = replacement.ToNumber();

            long offset = array.GetByteOffset(i);

            int[] buffer          = array.Buffer.Int32Array;
            int   bufferIndex     = (int)(offset >> 2);
            int   bytesPerElement = array.ElementSize;
            int   operand         = value.ToInt32();
            int   bitShift        = 0;
            int   mask            = -1;

            if (bytesPerElement != 4)
            {
                int byteShift = (int)(offset % 4);
                if (byteShift != 0 && !BitConverter.IsLittleEndian)
                {
                    byteShift = 4 - byteShift;
                }
                bitShift  = byteShift * 8;
                operand <<= bitShift;
                mask      = (bytesPerElement == 2 ? shortMask : byteMask)[byteShift];
            }
            else
            {
                int result;
                switch (operation)
                {
                case Operation.CompareExchange:
                    result = Interlocked.CompareExchange(ref buffer[bufferIndex], replacement.ToInt32(), operand);
                    break;

                case Operation.Exchange:
                    result = Interlocked.Exchange(ref buffer[bufferIndex], operand);
                    break;

                case Operation.Add:
                    result = unchecked (Interlocked.Add(ref buffer[bufferIndex], operand) - operand);
                    break;

                case Operation.Sub:
                    result = unchecked (Interlocked.Add(ref buffer[bufferIndex], -operand) + operand);
                    break;

                default:
                    goto fallback;
                }
                return(array.ArrayKind == TypedArrayKind.Uint32Array ? (EcmaValue)(uint)result : result);
            }
fallback:
            while (true)
            {
                int curValue = buffer[bufferIndex];
                int newValue = curValue;
                switch (operation)
                {
                case Operation.Or:
                    newValue |= operand;
                    break;

                case Operation.And:
                    newValue &= operand;
                    break;

                case Operation.Xor:
                    newValue ^= operand;
                    break;

                case Operation.Add:
                    newValue = unchecked (curValue + operand);
                    break;

                case Operation.Sub:
                    newValue = unchecked (curValue - operand);
                    break;

                case Operation.CompareExchange:
                    newValue = (curValue & mask) == (operand & mask) ? replacement.ToInt32() << bitShift : curValue;
                    break;

                case Operation.Exchange:
                    newValue = operand;
                    break;
                }
                if (bytesPerElement != 4)
                {
                    newValue = (curValue & ~mask) | (newValue & mask);
                }
                if (curValue == Interlocked.CompareExchange(ref buffer[bufferIndex], newValue, curValue))
                {
                    int result = (curValue & mask) >> bitShift;
                    switch (array.ArrayKind)
                    {
                    case TypedArrayKind.Int8Array:
                        return((sbyte)result);

                    case TypedArrayKind.Uint8Array:
                        return((byte)result);

                    case TypedArrayKind.Int16Array:
                        return((short)result);

                    case TypedArrayKind.Uint16Array:
                        return((ushort)result);

                    case TypedArrayKind.Uint32Array:
                        return((uint)result);
                    }
                    return(result);
                }
            }
        }