Silk Web is a container class that allows developers to safely use various containers in a true multi-threaded environment, where multiple threads could be accessing the same data at the same time.
It is written to be performance-oriented, though I have not yet had time to delve into assembly to further optimize it. At any rate, it was developed to make Warfare SDL possible - something that just couldn't be done with the currently available libraries which weren't quite thread-safe (STL). Even so, I recognize that I would not be the only one looking for such a solution, and so I am releasing this to the general public to be used as you see fit (under the BSD license).
Moreover, it is a simple thing to link data from one container into another and still maintain thread safety - hence the web. You could have multiple containers organized in different ways with the exact same data.
That's quickly becoming false. This started to change with Intel's Hyperthreading, which simulated a 2nd CPU some of the time, and now we have dual core CPUs from both Intel and AMD. These are all consumer-grade, not just server-grade.
Simple. Start by creating a pointer to SWDynamicDataType. Using this, create a new container. For example, if you want an SWList, do the following:
| SWDynamicDataType <Stuff> * MyList = new SWList <Stuff>; |
where Stuff represents the data type you're going to place in the list. Note that you do not need to make the type a pointer - that's all handled internally, so you will never be accessing a copy of the data directly from Silk Web, but instead the data itself.
Personally, I'd start by stuffing things into it. There's many ways of doing this - the most basic way is to send it an item to copy, which I'll describe below... and I'll also show how to send it a pointer instead so nothing is copied.
There are four insertion functions. These include: Append, PrePend, Push_Back, and Push_Front. The first two don't care where you are currently pointed to in the container, while the latter two only work if you are pointing at a valid section of the container. This can be done with SetBeginning, SetEnd, or either operator() or operator[].
All of the insertion functions take the same parameters: An object, a pointer to an object, or an SWDataPacket. Simply passing in an object will cause the container to create a copy of the object. If you want to avoid that, pass in a pointer to the object, and it will use that instead of making a copy. If you are passing in data from another container, then you pass in an SWDataPacket.
For example, below we will pass a pointer into the list we created earlier:
| MyList->Append(new Stuff); |
This appended a pointer to some new stuff to the end of the list. It did not make a copy of Stuff, but instead used the pointer supplied. Note that at this point, Silk Web believes that it owns the new stuff, so you don't have to worry about deleting it (deleting the final instance of the list will delete it).
Again, there are several functions you could use. These are: Get, GetConst, operator(), and operator[]. Each of these return references to the requested data (again, nothing is copied). Get and operator[] return modifiable references, while GetConst and operator() return constant references. This tells Silk Web what type of access is being requested so it can make sure nobody steps on somebody else's foot.
In order to use Get or GetConst, you must have the container set to a valid position.
An example of how to use one of these is below:
| (*MyList)[2].DoSomething(); |
The above de-references MyList so we could use the operator[] function to grab the 3rd element in the list. From there, we called DoSomething, a function that Stuff provides (called from the 3rd element in the list).
Now, once you have finished working on a particular element, you should call one of: Next, Prev, operator(), operator[], SetBeginning, SetEnd, UnGet, or Dislodge. If you change position in the container, you relinquish your lock on the data. If you have no further business in the container, use Dislodge to relinquish the lock and invalidate the position. To keep the position, simply use UnGet.
This is where Silk Web is strongest. The idea is to take an SWDataPacket from one container and insert it into another container. This can be done via the GetDP function. Use any insertion function to insert into another container. It's that simple. See the example below:
| SWDynamicDataType <Stuff> * MySecondList = new SWList <Stuff>; |
| MySecondList->Append(MyList->GetDP(2)); |
In the above example, we created a second list — MySecondList — just the same way we created the first list — MyList. We then use the insertion function Append to append an SWDataPacket obtained from the GetDP function in MyList. In this case, we used the data packet of the third element. It's that simple. From that point on, the same exact data exists in both lists. If it's modified in one, it's modified in the other. They also know about each other, so when one list is deleted, that data packet will not be deleted until the other list is also deleted. This works for however many lists you may want to use.
As a matter of fact, yes, there are. Each thread must have its own container. This does not mean that it does an element-by-element copy, or even an element-by-element pointer copy. This means that each container class will share the same physical container with their own private variables. An addition to one container is an addition to them all. The same for deletions. Below is an example of how to make this work:
| SWDynamicDataType <Stuff> * MyThirdList = new SWList <Stuff> (MyList); |
... And you're done. Essentially, all you do is create a new container and pass the shared container into the copy constructor. Now one thread can have MyList, and another thread can have MyThirdList.