private void Add(T value, ISingleLinkNode <T> previous) { //Let's create the node first var node = new SingleLinkNode <T>(value); //Now, we check if the list is empty, and if it is, then we add the node in the first place if (FirstNode == null) { FirstNode = node; FirstNode.Next = node; //All done return; } if (previous == LastNode || previous == null) { //wether the previous is null or last, it's always going to set the first node LastNode.Next = node; node.Next = FirstNode; if (previous == null) { FirstNode = node; } return; } var b = previous.Next; previous.Next = node; node.Next = b; }
public T Dequeue() { T result = default(T); bool HaveAdvancedHead = false; while (!HaveAdvancedHead) { SingleLinkNode <T> oldHead = head; SingleLinkNode <T> oldTail = tail; SingleLinkNode <T> oldHeadNext = oldHead.Next; if (oldHead == head) { if (oldHead == oldTail) { if (oldHeadNext == null) { return(default(T)); } CAS(ref tail, oldTail, oldHeadNext); } else { result = oldHeadNext.Item; HaveAdvancedHead = CAS(ref head, oldHead, oldHeadNext); } } } Interlocked.Decrement(ref count); return(result); }
// Can be called from another thread private void getBTDataFromThread(string data) { SingleLinkNode <string> node = new SingleLinkNode <string>(); node.Item = data; BTDataIn.Push(node); }
public override bool Pop(out T pItem) { pItem = default(T); SingleLinkNode oldHead = null; bool haveAdvancedHead = false; while (!haveAdvancedHead) { oldHead = mHead; SingleLinkNode oldTail = mTail; SingleLinkNode oldHeadNext = oldHead.Next; if (oldHead == mHead) { if (oldHead == oldTail) { if (oldHeadNext == null) { return(false); } CompareAndExchange(ref mTail, oldTail, oldHeadNext); } else { pItem = oldHeadNext.Item; haveAdvancedHead = CompareAndExchange(ref mHead, oldHead, oldHeadNext); } } } Interlocked.Decrement(ref Count); return(true); }
private void Add(T value, ISingleLinkNode <T> previous) { //Let's create the node first var node = new SingleLinkNode <T>(value); //Now, we check if the list is empty, and if it is, then we add the node in the first place if (FirstNode == null) { FirstNode = node; //All done return; } //Let's check if this element goes to the head node (special case) if (previous == null) { node.Next = FirstNode; FirstNode = node; return; } //Next, we set "previous"'s Next as the node's next node.Next = previous.Next; //Now, all we need is to set the "previous"'s Next as the node previous.Next = node; //Presto finito! }
// Can be called from another thread private void getBTDataFromThread(byte[] data) { SingleLinkNode <byte[]> node = new SingleLinkNode <byte[]>(); node.Item = data; BTDataIn.Push(node); }
public void Enqueue(T item) { SingleLinkNode <T> oldTail = null; SingleLinkNode <T> oldNext = null; SingleLinkNode <T> node = new SingleLinkNode <T>(item); /* 循环直到更新tail的next指向我们新的node节点 */ bool UpdatedNewLink = false; while (!UpdatedNewLink) { /* 保留tail和他的next一分本地拷贝,避免其他线程改动tail */ oldTail = tail; oldNext = oldTail.Next; /*必须用oldTail,本地拷贝, 因为tail可能被其他线程改动了*/ if (tail == oldTail) { if (oldNext == null && CAS(ref tail.Next, null, node)) { //tail.next = node Interlocked.Increment(ref count); UpdatedNewLink = true; } else { /*tail = tail.next*/ CAS(ref tail, oldTail, oldNext); } } } /* tail = node*/ CAS(ref tail, oldTail, node); }
public bool Shift(out T pItem) { pItem = default(T); if (mHead == null) { return(false); } SingleLinkNode oldHead = null; bool haveAdvancedHead = false; while (!haveAdvancedHead) { oldHead = mHead; if (oldHead != null) { SingleLinkNode oldHeadNext = oldHead.Next; if (CompareAndExchange(ref mHead, oldHead, oldHeadNext)) { pItem = oldHead.Item; return(true); } } } return(false); }
public bool Dequeue(out T pItem) { pItem = default(T); SingleLinkNode oldHead = null; bool haveAdvancedHead = false; while (!haveAdvancedHead) { oldHead = mHead; SingleLinkNode oldTail = mTail; SingleLinkNode oldHeadNext = oldHead.Next; if (oldHead == mHead) { if (oldHead == oldTail) { if (oldHeadNext == null) { return(false); } CompareAndExchange(ref mTail, oldTail, oldHeadNext); } else { pItem = oldHeadNext.Item; haveAdvancedHead = CompareAndExchange(ref mHead, oldHead, oldHeadNext); } } } return(true); }
public override void Push(T pItem) { SingleLinkNode oldTail = null; SingleLinkNode oldTailNext; SingleLinkNode newNode = new SingleLinkNode(); newNode.Item = pItem; bool newNodeWasAdded = false; while (!newNodeWasAdded) { oldTail = mTail; oldTailNext = oldTail.Next; if (mTail == oldTail) { if (oldTailNext == null) { newNodeWasAdded = CompareAndExchange(ref mTail.Next, null, newNode); } else { CompareAndExchange(ref mTail, oldTail, oldTailNext); } } } CompareAndExchange(ref mTail, oldTail, newNode); Interlocked.Increment(ref Count); }
public void Enqueue(T pItem) { SingleLinkNode oldTail = null; SingleLinkNode oldTailNext; SingleLinkNode newNode = new SingleLinkNode(); newNode.Item = pItem; bool newNodeWasAdded = false; while (!newNodeWasAdded) { oldTail = mTail; oldTailNext = oldTail.Next; if (mTail == oldTail) { if (oldTailNext == null) { newNodeWasAdded = CompareAndExchange(ref mTail.Next, null, newNode); } else { CompareAndExchange(ref mTail, oldTail, oldTailNext); } } } CompareAndExchange(ref mTail, oldTail, newNode); }
public bool Dequeue(out T item) { item = default(T); SingleLinkNode <T> oldHead = null; bool haveAdvancedHead = false; while (!haveAdvancedHead) { oldHead = head; SingleLinkNode <T> oldTail = tail; SingleLinkNode <T> oldHeadNext = oldHead.Next; if (oldHead == head) { if (oldHead == oldTail) { if (oldHeadNext == null) { return(false); } SyncMethods.CAS <SingleLinkNode <T> >(ref tail, oldTail, oldHeadNext); } else { item = oldHeadNext.Item; haveAdvancedHead = SyncMethods.CAS <SingleLinkNode <T> >(ref head, oldHead, oldHeadNext); } } } return(true); }
public void Enqueue(T item) { SingleLinkNode <T> oldTail = null; SingleLinkNode <T> oldTailNext; SingleLinkNode <T> newNode = new SingleLinkNode <T>(); newNode.Item = item; bool newNodeWasAdded = false; while (!newNodeWasAdded) { oldTail = tail; oldTailNext = oldTail.Next; if (tail == oldTail) { if (oldTailNext == null) { newNodeWasAdded = SyncMethods.CAS <SingleLinkNode <T> >(ref tail.Next, null, newNode); } else { SyncMethods.CAS <SingleLinkNode <T> >(ref tail, oldTail, oldTailNext); } } } SyncMethods.CAS <SingleLinkNode <T> >(ref tail, oldTail, newNode); }
/// <summary> /// Enqueue an item /// </summary> /// <param name="item">Item to enqeue</param> public void Enqueue(T item) { SingleLinkNode newNode = new SingleLinkNode { Item = item }; while (true) { SingleLinkNode oldTail = tail; SingleLinkNode oldTailNext = oldTail.Next; if (tail == oldTail) { if (oldTailNext != null) { CAS(ref tail, oldTail, oldTailNext); } else if (CAS(ref tail.Next, null, newNode)) { CAS(ref tail, oldTail, newNode); Interlocked.Increment(ref count); return; } } } }
public void Clear() { do { tail = head; }while (!CAS(ref head.Next, tail.Next, null)); }
/// <summary> /// Create a new instance. /// </summary> /// <param name="capacity">Number of hash buckets to use for the name table.</param> public LockFreeXmlNameTable(int capacity) { if(capacity <= 0) { throw new ArgumentException("capacity must be positive number", "capacity"); } _buckets = new SingleLinkNode<Entry>[capacity]; _capacityIsPowerOf2 = ((capacity & (capacity - 1)) == 0); }
// Update is called once per frame void Update() { // Check Concurrent Pool for data SingleLinkNode <byte[]> node = null; int dataInSize = 0; while (dataIn.Pop(out node)) { dataInSize++; byte[] data = node.Item; getDataDelegate(data); //Debug.Log("DataServerUpdate() got data"); // parse the data byte array into float values dataHandler.parseIncomingBTByteArray(data); ////profile time spent //after = DateTime.Now; //duration = after.Subtract(before); //before = DateTime.Now; //average_last_ten += duration.Milliseconds; //average_last_hundred += duration.Milliseconds; //count++; //big_count++; //if (big_count >= 100) //{ // Debug.Log("average of last hundred " + average_last_hundred / big_count); // big_count = 0; // average_last_hundred = 0; //} //if (count >= 10) //{ // Debug.Log("average of last ten " + average_last_ten / count); // count = 0; // average_last_ten = 0; //} } //if(dataInSize > 0) //Debug.Log("size of data q " + dataInSize); if (Input.GetKeyDown("space")) { //sendData("space key was pressed"); //var unixTimestamp = (DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalMilliseconds; //Debug.Log("unix time ms " + unixTimestamp); Debug.Log("time ms " + Time.time); } }
public void Push(SingleLinkNode <T> newNode) { newNode.Item = default(T); do { newNode.Next = head.Next; } while (!SyncMethods.CAS <SingleLinkNode <T> >(ref head.Next, newNode.Next, newNode)); return; }
public void Push(T item) { SingleLinkNode <T> newNode = new SingleLinkNode <T>(); newNode.Item = item; do { newNode.Next = head.Next; } while (!SyncMethods.CAS <SingleLinkNode <T> >(ref head.Next, newNode.Next, newNode)); }
void clientGetData(string data) { // In order to get back to the main thread // (Unity cannot handle scene modifications on other threads), // we put the data in a concurrent pool SingleLinkNode <string> node = new SingleLinkNode <string>(); node.Item = data; dataIn.Push(node); // Next part of the pipeline is DataHandler.Update() }
// Update is called once per frame void Update() { // Check Concurrent Pool for data SingleLinkNode <byte[]> node = null; if (dataIn.Pop(out node)) { byte[] data = node.Item; getDataDelegate(data); } }
public bool MoveNext() { if (currentNode == null) { currentNode = parent.mHead.Next; } else { currentNode = currentNode.Next; } return(currentNode != null); }
public bool Pop(out SingleLinkNode <T> node) { do { node = head.Next; if (node == null) { return(false); } } while (!SyncMethods.CAS <SingleLinkNode <T> >(ref head.Next, node, node.Next)); return(true); }
void getData(byte[] data) { //Debug.Log("getData() + " + data); // In order to get back to the main thread // (Unity cannot handle scene modifications on other threads), // we put the data in a concurrent pool SingleLinkNode <byte[]> node = new SingleLinkNode <byte[]>(); node.Item = data; dataIn.Push(node); // Next part of the pipeline is DataServer.Update() }
//--- Class Methods --- /// <summary> /// Add a named callback to the clock. /// </summary> /// <param name="name">Unique key for the callback.</param> /// <param name="callback">Callback action.</param> public static void AddCallback(string name, ClockCallback callback) { if (string.IsNullOrEmpty(name)) { throw new ArgumentNullException("name", "name cannot be null or empty"); } if (callback == null) { throw new ArgumentNullException("callback"); } // add callback #if LOCKFREEE var newNode = new SingleLinkNode <NamedClockCallback>(new NamedClockCallback(name, callback)); do { newNode.Next = _head; } while(!SysUtil.CAS(ref _head, newNode.Next, newNode)); #else lock (_syncRoot) { int index; // check if there is an empty slot in the callbacks array for (index = 0; index < _callbacks.Length; ++index) { if (_callbacks[index].Value == null) { _callbacks[index] = new NamedClockCallback(name, callback); return; } } // make room to add a new thread by doubling the array size and copying over the existing entries var newArray = new NamedClockCallback[2 * _callbacks.Length]; Array.Copy(_callbacks, newArray, _callbacks.Length); // assign new thread newArray[index] = new NamedClockCallback(name, callback); // update instance field _callbacks = newArray; } #endif }
void Update(object sender, EventArgs e) { // Check Concurrent Pool for data List <byte[]> dataList = new List <byte[]>(); SingleLinkNode <byte[]> node = null; while (BTDataIn.Pop(out node)) { dataList.Add(node.Item); } if (dataList.Count > 0) { // Turn the LIFO list into a FIFO list dataList.Reverse(); foreach (byte[] data in dataList) { getBTData(data); } } }
//--- Class Methods --- /// <summary> /// Add a named callback to the clock. /// </summary> /// <param name="name">Unique key for the callback.</param> /// <param name="callback">Callback action.</param> public static void AddCallback(string name, ClockCallback callback) { if(string.IsNullOrEmpty(name)) { throw new ArgumentNullException("name", "name cannot be null or empty"); } if(callback == null) { throw new ArgumentNullException("callback"); } // add callback #if LOCKFREEE var newNode = new SingleLinkNode<NamedClockCallback>(new NamedClockCallback(name, callback)); do { newNode.Next = _head; } while(!SysUtil.CAS(ref _head, newNode.Next, newNode)); #else lock(_syncRoot) { int index; // check if there is an empty slot in the callbacks array for(index = 0; index < _callbacks.Length; ++index) { if(_callbacks[index].Value == null) { _callbacks[index] = new NamedClockCallback(name, callback); return; } } // make room to add a new thread by doubling the array size and copying over the existing entries var newArray = new NamedClockCallback[2 * _callbacks.Length]; Array.Copy(_callbacks, newArray, _callbacks.Length); // assign new thread newArray[index] = new NamedClockCallback(name, callback); // update instance field _callbacks = newArray; } #endif }
public void Unshift(T pItem) { SingleLinkNode oldHead = null; var newNode = new SingleLinkNode(); newNode.Item = pItem; var newNodeWasAdded = false; while (!newNodeWasAdded) { oldHead = mHead.Next; newNode.Next = oldHead; if (mHead.Next == oldHead) { newNodeWasAdded = CompareAndExchange(ref mHead.Next, oldHead, newNode); } } CompareAndExchange(ref mHead, oldHead, newNode); }
/// <summary> /// Try to dequeue an item /// </summary> /// <param name="item">Dequeued item if the dequeue was successful</param> /// <returns>True if an item was successfully deqeued, otherwise false</returns> public bool TryDequeue(out T item) { while (true) { SingleLinkNode oldHead = head; SingleLinkNode oldHeadNext = oldHead.Next; if (oldHead == head) { if (oldHeadNext == null) { item = default(T); count = 0; return(false); } if (CAS(ref head, oldHead, oldHeadNext)) { item = oldHeadNext.Item; Interlocked.Decrement(ref count); return(true); } } } }
/// <summary> /// Add character sequence to nametable and get the string instance it represents. /// </summary> /// <remarks> /// If the sequence already exists, the existing string instance is returned. /// </remarks> /// <param name="chars">Source character array.</param> /// <param name="offset">Offset in chars.</param> /// <param name="length">Length of sub-array from chars.</param> /// <returns>String instance for character sequence.</returns> public override string Add(char[] chars, int offset, int length) { // check for the empty string and always return the built-in constant for it if(length == 0) { return string.Empty; } // locate entry based on hashcode of the supplied token int hashcode = chars.GetAlternativeHashCode(offset, length); int index = GetIndex(hashcode); SingleLinkNode<Entry> current = _buckets[index]; SingleLinkNode<Entry> entry = null; // check if a head node exists for the given hashcode if(current == null) { entry = new SingleLinkNode<Entry>(new Entry(hashcode, new string(chars, offset, length))); // try to update the head node with the new entry current = Interlocked.CompareExchange(ref _buckets[index], entry, null); // check if we succeeded, which means the provided token is now the reference token if(current == null) { return entry.Item.Token; } // otherwise, continue on since 'current' now has the updated head node } // loop until we successfully find or append the token SingleLinkNode<Entry> previous = null; while(true) { // check if we're looking for a short string (in that case, we skip the hashcode check) if(length < 12) { // loop over all entries until we exhaust them or find a match for(; current != null; current = current.Next) { // do only an ordinal string comparison since the token is short if(CompareStringToCharArray(current.Item.Token, chars, offset, length) == 0) { return current.Item.Token; } previous = current; } } else { // loop over all entries until we exhaust them or find a match for(; current != null; current = current.Next) { // do only an ordinal string comparison since the token is short if((current.Item.HashCode == hashcode) && (CompareStringToCharArray(current.Item.Token, chars, offset, length) == 0)) { return current.Item.Token; } previous = current; } } // NOTE: it's possible that an earlier attempt already initialized 'entry' entry = entry ?? new SingleLinkNode<Entry>(new Entry(hashcode, new string(chars, offset, length))); // try to update the previous node with the new entry current = Interlocked.CompareExchange(ref previous.Next, entry, null); // check if we succeeded, which means the provided token is now the reference token if(current == null) { // provided token was added return entry.Item.Token; } // otherwise, continue on since 'current' now has the updated next node } }
private static void MasterTickThread(object _unused) { DateTime last = DateTime.UtcNow; while (_running) { // wait until next iteration Thread.Sleep(_intervalMilliseconds); // get current time and calculate delta DateTime now = DateTime.UtcNow; TimeSpan elapsed = now - last; last = now; // execute all callbacks #if LOCKFREEE SingleLinkNode <NamedClockCallback> previous = null; var current = _head; while (current != null) { var key = current.Item.Key; var callback = current.Item.Value; if (callback == null) { // remove linked node if (previous == null) { // there might be contention on the head item of the callback list; // hence, we need to do it in a threadsafe fashion SingleLinkNode <NamedClockCallback> head; SingleLinkNode <NamedClockCallback> next; do { head = _head; next = head.Next; } while(!SysUtil.CAS(ref _head, head, next)); } else { // other threads don't operate on non-head items of the callback list previous.Next = current.Next; } // clear out the item entirely to indicate we've removed it current.Item = new NamedClockCallback(null, null); } else { try { callback(now, elapsed); } catch (Exception e) { _log.ErrorExceptionMethodCall(e, "GlobalClock callback failed", key); } } previous = current; current = current.Next; } #else lock (_syncRoot) { var callbacks = _callbacks; foreach (NamedClockCallback callback in callbacks) { if (callback.Value != null) { try { callback.Value(now, elapsed); } catch (Exception e) { _log.ErrorExceptionMethodCall(e, "GlobalClock callback failed", callback.Key); } } } } #endif } // indicate that this thread has exited _stopped.Set(); }
private static bool CompareAndExchange(ref SingleLinkNode pLocation, SingleLinkNode pComparand, SingleLinkNode pNewValue) { return (pComparand == Interlocked.CompareExchange(ref pLocation, pNewValue, pComparand)); }
public void Reset() { currentNode = parent.mHead.Next; }