From: Matt Hurd (matt.hurd_at_[hidden])
Date: 2004-09-22 07:55:07
On Wed, 22 Sep 2004 06:41:07 -0400, David Abrahams
> Matt Hurd <matt.hurd_at_[hidden]> writes:
> >> On Tue, 21 Sep 2004 17:37:03 +0200, Alexander Terekhov <terekhov_at_[hidden]> wrote:
> >> Matt Hurd wrote:
> >> First off, atomocity without memory ordering and visibility protocol
> >> is pretty useless.
> > For many, perhaps most, tasks yes. However, think of a database
> > without locking... it can still be useful with optimistic concurrency
> > for some styles of application. Atomic memory transactions are just a
> > guarantee that the "bits" are consistent.
> They typically don't exist for "records" of more than one word, if
> I'm not mistaken. How useful is that for a database?
Sorry Dave, I'm not sure I understand your question which respect to
the metaphor I was using.
I just saw the C++ memory paper a few hours ago:
I see what I am using as an example is also addressed here. It also
splits the memory model into the three aspects I suggested atomicity,
visibility and ordering.
My non-suggestion , it was just an example for platform specific
necessity which hijacked the thread ;-) , boost::needs_lock<T> that
perhaps would be better named something that better reflects the
potential for memory consistency if alignment is appropriate.
This addresses incompletely the atomicity aspect of the memory model.
The other main part to determining atomicity is alignment. That is
being an rvalue with correct alignment, which may not be determined
from the type. This might be assumed in code or an additional helper
such as boost::is_memory_atomic_aligned<T>(t) plus, perhaps, a
complete package with boost::is_memory_atomic<T>(t). Unfortunately
only maybe_memory_atomic would be compile but this would be OK as
you'd usually be assuming appropriate alignment anyway.
A default implementation for boost::maybe_memory_atomic<T> would
return false. Though perhaps a sizeof 1 would be a reasonable
assumption until the usual pdp-11 caveats get dragged up ;-)
For ia32, Pentium and above, it would return true for sizeof(T) <= 8.
For ia32, 486, it would return true for sizeof(T) <= 4.
Not sure what the 386 version should return
An immediate problem may be that an 8 byte type on P6 might resolve to
two 4 byte types and thus two independent reads and writes. Thus
perhaps, is fundamental or POD, and an appropriate sizeof might be
nessary to consider as part of the specialization framework for a
In terms of visibility the approach of redefining what "volatile"
means seems useful as discussed in the paper. Meanwhile a simple
fence / flushing like structure might be enough to many things to get
by as a library solution. Perhaps a scoped fence-like thingy that
has acquire / release / flushing semantics...
typedef synch::multi_thread threading_policy;
which guarantees ordering and visibility of all RW operations to be A
-> B -> C; Or should this just be limited to A->B, or , alternatively
This may not be possible on some architectures and thus it should
assert so at least you know it is unsafe. On a strictly ordered
architecture with simple consistency, e.g. only ever a single
processor with sequential semantics guaranteed by the hardware and
compiler, it would be a NOP and thus optimized away. Any suggestions
for the efficient implementation for the constructor and destructor
for pentium / p6 etal?
Similarly, perhaps a memory_visibility scoped var could guarantee the
visibility of B ops.
Perhaps a memory_ordering scoped var could guarantee appropriate
ordering, say A->B->C or A->B or B->C which ever would be commonly
inexpensive across typical platforms, without having to guarantee
visibility, but I'm not sure ordering guarantees are too useful
without visibility, but combined with volatile for something like
hardware register access, perhaps it is.
Note that using such a memory_guarantee still requires appropriate
memory consistency, this isn't included as part of the
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk