> What guarantees is shared supposed to provide?
>
> Shared means that multiple threads can access the data. The
> guarantee is that if it is not shared, and not immutable, that
> only the current thread can see it. 

What if I have a thread that contains some shared data? Should
the thread be created as shared, be cast to shared after
construction or not be shared and fine grained shared applied
to the respective shared data fields?

> What does shared have to do with synchronization?
>
> Only shared data can be synchronized. It makes no sense to
> synchronize thread local data. 

Define synchronized. With atomic ops on word size items this
is clear, but what does it mean for aggregates? The language
shows us no connection between synchronization and the shared
data. What is one unit of data that is to be synchronized?

> What does shared have to do with memory barriers?
>
> Reading/writing shared data emits memory barriers to ensure
> sequential consistency (not implemented).

That's exactly the problem. It assumes the unit is a word size
item. If I have a Mutex to protect my unit of shared data, I
don't need "volatile" handling of shared data.

    private shared class SomeThread : Thread
    {
    private:

        Condition m_condition;
        bool m_shutdown = false;
        ...
    }

m_shutdown will be shared and it is shared data, but it is
synchronized by the Mutex contained in that condition.
Automatic memory barriers and such would only slow down
execution.

> What are the semantics of casting FROM unshared TO shared?
>
> Make sure there are no other unshared references to that same
> data.
>
> What are the semantics of casting FROM shared TO
> unshared?
>
> Make sure there are no other shared references to that same
> data.

That's just wrong to ask. `SomeThread` is a worker thread and
data is passed to it regularly through a shared reference that
is certainly never going away until the thread dies.
Yet I must be able to "unshare" it's list of work items to
process them.

Now let's say I have an "empty" property. Shared or unshared?

        override @property bool empty() const
        {
                return m_list.empty;
        }

It is only called internally by the thread itself after
entering a certain critical section. I _know_ that m_list wont
be accessible by other threads while .empty is running.

But this seeming 1:1 relationship between entering "the"
critical section and stripping shared is of course
non-existent. Aggregates may contain Mutexes protecting
different fields or even stacking on top of each other.

So the text should read:

> What are the semantics of casting FROM shared TO unshared?
>
> Make sure that during the period the data is unshared, no
> other thread can modify those parts of it that you will be
> accessing. If you don't use synchronization objects with
> built-in memory-barriers like a Mutex, it is your
> responsibility to properly synchronize data access through
> e.g. atomicLoad/Store.

That at least in general sanctifies casting away shared for
the purpose of calling a method under protection of a user
defined critical section.

-- 
Marco

Reply via email to