|
"Dmitriy Vyukov" <dvyukov@gmail.com> wrote in message
news:7510692e-190f-4aa7-bfb5-3b53943fb6f0@b2g2000yqi.googlegroups.com...
> On 20 ноя, 21:36, "James" <n...@spam.invalid> wrote:
> > Here is simple example:
> >
> > static char string[] = "XXXXX XXXXX";
> > static bool volatile done = false;
> > static pthread_mutex_t mutex;
> >
> > void thread_1() {
> > strcpy(string, "Hello World");
> > pthread_mutex_lock(&mutex);
> > pthread_mutex_unlock(&mutex);
> > done = true;
> > }
> If pthread_mutex_lock() is considered only as acquire and
> pthread_mutex_unlock() is considered only as release, then
> pthread_mutex_lock() can hoist above and pthread_mutex_unlock() can
> sink below:
> pthread_mutex_lock(&mutex);
> strcpy(string, "Hello World");
> done = true;
> pthread_mutex_unlock(&mutex);
> And then there are 2 normal memory accesses that can be reordered:
> pthread_mutex_lock(&mutex);
> done = true;
> strcpy(string, "Hello World");
> pthread_mutex_unlock(&mutex);
Okay. So, assuming that I changed the code to what Chris M. Thomasson
suggested:
http://groups.google.com/group/comp.programming.threads/msg/d52c83e1d755091d
void thread_1() {
strcpy(string, "Hello World");
pthread_mutex_lock(&mutex);
pthread_mutex_unlock(&mutex);
done = true;
}
void other_threads() {
while (! done) sched_yield();
pthread_mutex_lock(&mutex);
pthread_mutex_unlock(&mutex);
assert(! strcmp(string, "Hello World"));
}
And assuming all the hoist/sink reorderings that can occur, the "worst"
possible outcome could look like:
void thread_1() {
pthread_mutex_lock(&mutex);
done = true;
strcpy(string, "Hello World");
pthread_mutex_unlock(&mutex);
}
void other_threads() {
pthread_mutex_lock(&mutex);
assert(! strcmp(string, "Hello World"));
while (! done) sched_yield();
pthread_mutex_unlock(&mutex);
}
AFAICT, that will still work. Dmitriy, can a particular reordering break the
code? It seems like if the lock can hoist above and the unlock can sink
below, all's that does is "widen" the critical section, and does not seem
like it would be able to break the code in the sense of the assertion
failing.
Also, I notice that Chris Thomasson wrapped up the lock/unlock pair in a
single function and said to externally compile it. It think he was trying to
reduce compiler level reordering. It seems like you are talking about
hardware reordering? Also, if the pthread_mutex_lock has a storeload, then
is it still considered to have acquire semantics? Or is it something
stronger?
Sorry for all the questions.
Thanks!
:^)
|
|
0
|
|
|
Reply
|
James
|
11/21/2009 2:28:54 PM
|
Header
|
Report
as Spam
|
|
On Nov 21, 5:28=A0pm, "James" <n...@spam.invalid> wrote:
> And assuming all the hoist/sink reorderings that can occur, the "worst"
> possible outcome could look like:
>
> void thread_1() {
> =A0 =A0 pthread_mutex_lock(&mutex);
> =A0 =A0 done =3D true;
> =A0 =A0 strcpy(string, "Hello World");
> =A0 =A0 pthread_mutex_unlock(&mutex);
>
> }
>
> void other_threads() {
> =A0 =A0 pthread_mutex_lock(&mutex);
> =A0 =A0 assert(! strcmp(string, "Hello World"));
> =A0 =A0 while (! done) sched_yield();
> =A0 =A0 pthread_mutex_unlock(&mutex);
>
> }
>
> AFAICT, that will still work. Dmitriy, can a particular reordering break =
the
> code? It seems like if the lock can hoist above and the unlock can sink
> below, all's that does is "widen" the critical section, and does not seem
> like it would be able to break the code in the sense of the assertion
> failing.
Humm... I think you are right, I do not see any reordering that breaks
the code. I just mixed up your variant with the following variant
(that I tried to use by myself):
// thread 1
g_data[index] =3D produce_data();
// here we are using "mutex barrier"
pthread_mutex_lock();
pthread_mutex_unlock();
g_index =3D index;
// thread 2
while (*(int volatile*)&g_index =3D=3D 0) {/*spin*/}
// here we are relying on the fact that compiler and hardware respect
control dependencies
consume_data(g_data[g_index]);
And this code can be broken by the reordering.
So it seems that "mutex barrier" can be used iff it is used on both
sides.
> Also, I notice that Chris Thomasson wrapped up the lock/unlock pair in a
> single function and said to externally compile it. It think he was trying=
to
> reduce compiler level reordering. It seems like you are talking about
> hardware reordering? Also, if the pthread_mutex_lock has a storeload, the=
n
> is it still considered to have acquire semantics? Or is it something
> stronger?
Yes, many implementations use full barrier in lock(), and sometimes in
unlock() too.
--
Dmitriy V'jukov
|
|
0
|
|
|
Reply
|
Dmitriy
|
11/21/2009 5:57:06 PM
|
Header
|
Report
as Spam
|
|
"Dmitriy Vyukov" <dvyukov@gmail.com> wrote in message
news:3792d789-ec85-4c03-8b52-34b8a30ce85b@u7g2000yqm.googlegroups.com...
On Nov 21, 5:28 pm, "James" <n...@spam.invalid> wrote:
> > And assuming all the hoist/sink reorderings that can occur, the "worst"
> > possible outcome could look like:
> >
> > void thread_1() {
> > pthread_mutex_lock(&mutex);
> > done = true;
> > strcpy(string, "Hello World");
> > pthread_mutex_unlock(&mutex);
> >
> > }
> >
> > void other_threads() {
> > pthread_mutex_lock(&mutex);
> > assert(! strcmp(string, "Hello World"));
> > while (! done) sched_yield();
> > pthread_mutex_unlock(&mutex);
> >
> > }
> >
> > AFAICT, that will still work. Dmitriy, can a particular reordering break
> > the
> > code? It seems like if the lock can hoist above and the unlock can sink
> > below, all's that does is "widen" the critical section, and does not
> > seem
> > like it would be able to break the code in the sense of the assertion
> > failing.
> Humm... I think you are right, I do not see any reordering that breaks
> the code.
> I just mixed up your variant with the following variant
> (that I tried to use by myself):
[...]
> And this code can be broken by the reordering.
> So it seems that "mutex barrier" can be used iff it is used on both
> sides.
Assuming that the mutex lock can rise and the unlock can sink, can you
"force" a certian ordering by using more than one mutex? Think of this:
static int g_state = 0;
static bool volatile g_done = 0;
static pthread_mutex_t g_mutex;
struct thread
{
pthread_mutex_t m_mutex;
void lock() { pthread_mutex_lock(&m_mutex); }
};
void thread_1(thread& t)
{
g_state = 666;
}
> > Also, I notice that Chris Thomasson wrapped up the lock/unlock pair in a
> > single function and said to externally compile it. It think he was
> > trying to
> > reduce compiler level reordering. It seems like you are talking about
> > hardware reordering? Also, if the pthread_mutex_lock has a storeload,
> > then
> > is it still considered to have acquire semantics? Or is it something
> > stronger?
> Yes, many implementations use full barrier in lock(), and sometimes in
> unlock() too.
|
|
0
|
|
|
Reply
|
James
|
11/21/2009 8:21:04 PM
|
Header
|
Report
as Spam
|
|
On Nov 22, 10:31=A0pm, "Chris M. Thomasson" <n...@spam.invalid> wrote:
> I modeled this senerio in Relacy:
>
> http://relacy.pastebin.com/f4b36dd98
>
> It cannot find a way to break it either.
>
> ;^)
Note that one still have to use std::atomic for g_flag, even if actual
"synchronization" is provided by mutexes. And if one have std::atomic,
then there is a little sense in using mutexes for synchronization in
this example.
However, I think there is still benefit in coding with Relacy not
exactly what you have in production. Because if Relacy finds some
issue in a test, and then you manually verifies that the same issue
applies to the original production code, well, it's a plus. Some
issues may be masked. though.
> > I just mixed up your variant with the following variant
> > (that I tried to use by myself):
> > // thread 1
> > g_data[index] =3D produce_data();
> > // here we are using "mutex barrier"
> > pthread_mutex_lock();
> > pthread_mutex_unlock();
> > g_index =3D index;
> > // thread 2
> > while (*(int volatile*)&g_index =3D=3D 0) {/*spin*/}
> > // here we are relying on the fact that compiler and hardware respect
> > control dependencies
> > consume_data(g_data[g_index]);
> > And this code can be broken by the reordering.
> > So it seems that "mutex barrier" can be used iff it is used on both
> > sides.
>
> Yes. I was wondering how to model this in Relacy:
>
> http://groups.google.com/group/comp.programming.threads/msg/3f8ef89bf...
>
> Humm... Would Relacy treat the per-thread mutex actions like:
> _______________________________________________________________
> void thread_1()
> {
> =A0 =A0 std::mutex m;
> =A0 =A0 m.lock($);
>
> T1-M1: =A0 =A0m.unlock($);
> T1-M2: =A0 =A0m.lock($);
>
> =A0 =A0 m.unlock($);
>
> }
>
> void thread_2()
> {
> =A0 =A0 std::mutex m;
> =A0 =A0 m.lock($);
>
> T2-M1: =A0 =A0m.unlock($);
> T2-M2: =A0 =A0m.lock($);
>
> =A0 =A0 m.unlock($);}
>
> _______________________________________________________________
>
> as being equivalent to:
> _______________________________________________________________
> void thread_1()
> {
> T1-M1: =A0 =A0std::atomic_thread_fence(std::memory_order_release);
> T1-M2: =A0 =A0std::atomic_thread_fence(std::memory_order_acquire);
>
> }
>
> void thread_2()
> {
> T2-M1: =A0 =A0std::atomic_thread_fence(std::memory_order_release);
> T2-M2: =A0 =A0std::atomic_thread_fence(std::memory_order_acquire);}
>
> _______________________________________________________________
>
> ?
>
> I don't think it will. Even though it would in practice, asymmetric
> synchronization schemes aside for a moment of course...
Relacy will treat them differently.
Mutex lock/unlock is basically the same as acquire/release operation
on a variable. Stand-alone fences are more powerful in some sense,
because they do not bind to a particular variable. And at the same
time stand-alone fences (except seq_cst) are weaker, because they do
not establish total order over operations (as store/RMW on a
particular atomic).
--
Dmitriy V'jukov
|
|
0
|
|
|
Reply
|
Dmitriy
|
11/23/2009 6:47:19 AM
|
Header
|
Report
as Spam
|
|
"Dmitriy Vyukov" <dvyukov@gmail.com> wrote in message
news:8cf1c9ff-fa83-4de1-8095-e27c64434e07@p19g2000vbq.googlegroups.com...
On Nov 22, 10:31 pm, "Chris M. Thomasson" <n...@spam.invalid> wrote:
> > I modeled this senerio in Relacy:
> >
> > http://relacy.pastebin.com/f4b36dd98
> >
> > It cannot find a way to break it either.
> >
> > ;^)
> Note that one still have to use std::atomic for g_flag, even if actual
> "synchronization" is provided by mutexes. And if one have std::atomic,
> then there is a little sense in using mutexes for synchronization in
> this example.
> However, I think there is still benefit in coding with Relacy not
> exactly what you have in production. Because if Relacy finds some
> issue in a test, and then you manually verifies that the same issue
> applies to the original production code, well, it's a plus. Some
> issues may be masked. though.
Agreed.
> > I just mixed up your variant with the following variant
> > (that I tried to use by myself):
[...]
>
> Yes. I was wondering how to model this in Relacy:
>
> http://groups.google.com/group/comp.programming.threads/msg/3f8ef89bf...
>
> Humm... Would Relacy treat the per-thread mutex actions like:
> _______________________________________________________________
[...]
> _______________________________________________________________
>
> as being equivalent to:
> _______________________________________________________________
[...]
> _______________________________________________________________
>
> ?
>
> I don't think it will. Even though it would in practice, asymmetric
> synchronization schemes aside for a moment of course...
> Relacy will treat them differently.
> Mutex lock/unlock is basically the same as acquire/release operation
> on a variable.
I think using mutexs this way would be undefined behavior wrt the C++0x.
> Stand-alone fences are more powerful in some sense,
> because they do not bind to a particular variable. And at the same
> time stand-alone fences (except seq_cst) are weaker, because they do
> not establish total order over operations (as store/RMW on a
> particular atomic).
I personally like stand-alone fences because IMHO they are more flexible. I
can put them exactly where I need them; e.g.:
________________________________________________________________
#define N 10
static int g_values[N] = { NULL };
static std::atomic<bool> g_flags[N] = { NULL };
void thread_1()
{
for (size_t i = 0; i < N; ++i)
{
g_values[i] = 666;
}
std::atomic_thread_fence(std::memory_order_release);
for (size_t i = 0; i < N; ++i)
{
g_flags[i].store(true, std::memory_order_relaxed);
}
}
void other_threads()
{
retry:
for (size_t i = 0; i < N; ++i)
{
if (! g_flags[i].load(std::memory_order_relaxed))
{
spin();
goto retry;
}
}
std::atomic_thread_fence(std::memory_order_acquire);
for (size_t i = 0; i < N; ++i)
{
assert(g_values[i] == 666);
}
}
________________________________________________________________
As far as a total order over operations, I am not sure I understand what you
mean. I expect the following to be out of order:
________________________________________________________________
std::atomic<int> g_value1;
std::atomic<int> g_value2;
void foo()
{
g_value1.store(1, std::memory_order_relaxed);
std::atomic_thread_fence(std::memory_order_release);
g_value2.load(std::memory_order_relaxed);
}
________________________________________________________________
but not this:
________________________________________________________________
std::atomic<int> g_value1;
std::atomic<int> g_value2;
void foo()
{
g_value1.store(1, std::memory_order_relaxed);
std::atomic_thread_fence(std::memory_order_seq_cst);
g_value2.load(std::memory_order_relaxed);
}
________________________________________________________________
|
|
0
|
|
|
Reply
|
Chris
|
11/25/2009 7:25:18 PM
|
Header
|
Report
as Spam
|
|
On 25 =D0=BD=D0=BE=D1=8F, 22:25, "Chris M. Thomasson" <n...@spam.invalid> w=
rote:
> > Stand-alone fences are more powerful in some sense,
> > because they do not bind to a particular variable. And at the same
> > time stand-alone fences (except seq_cst) are weaker, because they do
> > not establish total order over operations (as store/RMW on a
> > particular atomic).
>
> I personally like stand-alone fences because IMHO they are more flexible.=
I
> can put them exactly where I need them; e.g.:
> ________________________________________________________________
> #define N 10
>
> static int g_values[N] =3D { NULL };
> static std::atomic<bool> g_flags[N] =3D { NULL };
>
> void thread_1()
> {
> =C2=A0 =C2=A0 for (size_t i =3D 0; i < N; ++i)
> =C2=A0 =C2=A0 {
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 g_values[i] =3D 666;
> =C2=A0 =C2=A0 }
>
> =C2=A0 =C2=A0 std::atomic_thread_fence(std::memory_order_release);
>
> =C2=A0 =C2=A0 for (size_t i =3D 0; i < N; ++i)
> =C2=A0 =C2=A0 {
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 g_flags[i].store(true, std::memory_order_rela=
xed);
> =C2=A0 =C2=A0 }
>
> }
>
> void other_threads()
> {
> retry:
> =C2=A0 =C2=A0 for (size_t i =3D 0; i < N; ++i)
> =C2=A0 =C2=A0 {
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 if (! g_flags[i].load(std::memory_order_relax=
ed))
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 {
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 spin();
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 goto retry;
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 }
> =C2=A0 =C2=A0 }
>
> =C2=A0 =C2=A0 std::atomic_thread_fence(std::memory_order_acquire);
>
> =C2=A0 =C2=A0 for (size_t i =3D 0; i < N; ++i)
> =C2=A0 =C2=A0 {
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 assert(g_values[i] =3D=3D 666);
> =C2=A0 =C2=A0 }}
>
> ________________________________________________________________
AFAIR, Paul McKenney present something along the lines of your example
as a motivating example for stand-alone fences.
> As far as a total order over operations, I am not sure I understand what =
you
> mean. I expect the following to be out of order:
> ________________________________________________________________
> std::atomic<int> g_value1;
> std::atomic<int> g_value2;
>
> void foo()
> {
> =C2=A0 =C2=A0 g_value1.store(1, std::memory_order_relaxed);
> =C2=A0 =C2=A0 std::atomic_thread_fence(std::memory_order_release);
> =C2=A0 =C2=A0 g_value2.load(std::memory_order_relaxed);}
>
> ________________________________________________________________
Regarding total order I mean that your above code won't work (even if
release is replaced with acq_rel).
However if we replace stand-alone acq_rel fence with atomic RMW with
acq_rel ordering:
g_value1.store(1, std::memory_order_relaxed);
g_sync.exchange(0, std::memory_order_acq_rel);
g_value2.load(std::memory_order_relaxed);}
It must work. Because RMW on a particular variable establishes total
order (over all RMW on the variable), while stand-alone fence not.
--
Dmitriy V'jukov
|
|
0
|
|
|
Reply
|
Dmitriy
|
11/28/2009 9:03:16 AM
|
Header
|
Report
as Spam
|
|
"Dmitriy Vyukov" <dvyukov@gmail.com> wrote in message
news:f9e5c87c-5280-4a32-886e-b2ac9d30dd3d@a32g2000yqm.googlegroups.com...
On 25 ноя, 22:25, "Chris M. Thomasson" <n...@spam.invalid> wrote:
>
> > > Stand-alone fences are more powerful in some sense,
> > > because they do not bind to a particular variable. And at the same
> > > time stand-alone fences (except seq_cst) are weaker, because they do
> > > not establish total order over operations (as store/RMW on a
> > > particular atomic).
[...]
> > As far as a total order over operations, I am not sure I understand what
> > you
> > mean. I expect the following to be out of order:
> > ________________________________________________________________
> > std::atomic<int> g_value1;
> > std::atomic<int> g_value2;
> >
> > void foo()
> > {
> > g_value1.store(1, std::memory_order_relaxed);
> > std::atomic_thread_fence(std::memory_order_release);
> > g_value2.load(std::memory_order_relaxed);}
> >
> > ________________________________________________________________
> Regarding total order I mean that your above code won't work (even if
> release is replaced with acq_rel).
Right. When I wrote:
"I expect the following to be out of order"
I meant that I expect the load from `g_value2' to be able to rise above the
store to `g_value1'.
> However if we replace stand-alone acq_rel fence with atomic RMW with
> acq_rel ordering:
> g_value1.store(1, std::memory_order_relaxed);
> g_sync.exchange(0, std::memory_order_acq_rel);
> g_value2.load(std::memory_order_relaxed);}
> It must work. Because RMW on a particular variable establishes total
> order (over all RMW on the variable), while stand-alone fence not.
I would also expect this to work:
___________________________________________________
g_value1.store(1, std::memory_order_relaxed);
std::atomic_thread_fence(std::memory_order_seq_cst);
g_value2.load(std::memory_order_relaxed);
___________________________________________________
|
|
0
|
|
|
Reply
|
Chris
|
11/28/2009 7:59:56 PM
|
Header
|
Report
as Spam
|
|
18 Replies
140 Views
Similiar Articles: [comp.publish.cdrom] CD-Recordable FAQ, Part 1/4 - comp.publish ...(1) Platform. PC, Mac, Sun, whatever. (2) Operating system, with version. ... CD-RW discs have a different formulation, and may work even on players that FileMaker 7 - must be damn good - comp.databases.filemaker ...never will be cross-platform. That's one of the things I don't like about it. ... doing the work, even if the Access UI was used to create the MDB file. ... e1000g on sparc (solaris 10 update1) - comp.unix.solaris ...(FCS), and they work OK. I added one to my sparc netra ... update 1. I can plumb the interface, and even ping across it, but any ... SPARC Enterprise Servers Hardware Platform ... OpenGL Directshow performance - comp.graphics.api.opengl ...uploading speed on some platform this is quite good. But uploading spent ... work. Theres even a d3d mode called adapter group which allows multiple ESMTP inspection problem (ASA 7.2) - comp.dcom.sys.cisco ...<eutp95$r1l$1@ss408.t-com.hr ... drops some ESMTP connections even if all parameters has been set to log only. I'm new to ASA platform ... problem where ESMTP is working to ... Grayscale Graphics Editor for HP50g (on-calc editor library ...>the ARM platform supports greyscale. but the hp50g/49g+ has no support >for those. ... compatibility, at the same time emulator may end up work even faster. manjo problem with mixed c and fortran code - comp.lang.fortran ...to work if you use the specified compiler. Without a prototype, and often even with one, C promotes anything ... code require porting for any other platform, even ... CHARS() in default stream - comp.lang.rexx... without blocking, but I find that it returns "1" even if ... *very* dependent upon platform. Further, though, it states ... what you want (with a bit of work and experimentation). Any way to determine host endianness by template-metaprogramming ...truck, and occasionally use it even when he isn't sure it will work. ... it only test the ediannes of the platform ... the program offered above will work. > Anyway, since one ... put a dot over a character in Matlab plot using interpreter(Tex ...I even tried out to wokr with set(0 ... > but it does not work too. > Is there any way ... Hi, Can you provide some version and platform information? t=0:0.001:1; 32 bit applet on 64 bit Java? - comp.lang.java.programmer ...you naturally have to provide one for every platform you wish to ... Are java applications even different when ... 2048 bit certificate does not work in jre 1.5 13 - comp ... Real-Time Windows Target and RS232 communication? - comp.soft-sys ...... at baudrate 115200 (or even higher), can RTWT handle this? 2. What is the minimum possible sample time RTWT can achieve when working ... 2041-real-time-control-platform ... Global static destructors called when a dynamic library is ...AFAIK, you can rely on it on all modern platform. ... linuces that have gcc 3.2 or newer (it may work with 3.0 or 3.1 ... platforms where it won't work even with recent gcc ... create a gl context without a window - comp.graphics.api.opengl ...news:ccuhvt$cj$1@nic.grnet.gr... > Platform: Win32 ... myself and found not to be the only one latter so it might work ... Now if the window isn't even open then ... problems with "substitute" function - comp.databases ...This applies even if the 'find' text begins with "==". ... But I can't get the 'substitute' to work - it just ... nb 2 - are you on the same platform as me? cheers FQ short/longnamepaths (Win32, Regina) - comp.lang.rexxSince it works from W98 or NT4 up - i.e. it does not work on ... different Batch techniques, so I am set for a platform-specific solution even if not a REXX one. Set JComboBox 's JTextField into JFormattedTextField, how ...Dear all, Any example to follow for the question I post. I wish to replace the JTextField of JComboBox by JFormattedTextField. Thank you. ... still not able to get NTP to sync on windows 7 even w/ more ...As I understand it, that likely means ntp is working as intended on that platform. ... (ntpd.exe) from this one source. So situation is even worse I think than saying "4 ... Question about ADC - comp.dspyour platform allows such a high I/O data ... don't know if it would work at sample rates as low as > 2kS/s (as you obviously prefer according to your post). Storing binary data in String/StringBuffer - comp.lang.java ...... to binary data.>> Text-oriented protocols can work well, even if used for binary data (consider> HTTP for one ... StringBuffer (Java 2 Platform SE 5.0) A string buffer is ... Forklift Work Platforms and Man Baskets - Budget Forklift/Skid ...Forklift Work Platform Features: FULL LENGTH GATES are now Standard on All Work Platforms. ALL WORK PLATFORMS ship with a Work Safe Booklet. The Work Safe ... Do enhancements' passive bonuses work even when not slotted ...I don't understand how the passive bonuses work. I don't think the game ever explained them. Someone clarify for me? For example if I have Strife's Offering simply in ... Amazon.com: Werner AP-20-MP6 225-Pound Capacity Work Platform ...a) There is only one size Platform made by Werner in this design -- even though you will see different ... All features combine to make Werner's Work Platform one of those ... Rip Rowan - Google+ - Stevey's Google Platforms Rant I was at ...Even if individuals do, even if YOU do, it doesn't matter one bit ... little or no repercussions at work ... One to retrofit a "platform" to the run-away success DMS ... Aerial work platform - Wikipedia, the free encyclopediaAn aerial work platform (AWP), also known as an aerial device or elevating work platform ... Even models not fitted with a control panel at the base are usually fitted with ... What's in Oracle VM VirtualBox 4.1? (The Fat Bloke Sings)So with 4.1 we've enhanced VirtualBox to work great on all sizes of systems, even up to systems with 1 Terabyte of RAM. ... client, sometimes we still need the windows platform ... Mika Mobile: Our Future with AndroidWe could re-engineer how Battleheart accesses its data to work with this ... not a weapon to be swung in the never-ending holy war between fans of one platform ... Interview: Opera on the Web of Devices - W3C BlogSome carriers are even promoting the browser ... One of the things we're working on is GPU-accelerated WebGL support for ... People designing for one platform miss out on what ... Android 2.2 Platform Highlights | Android DevelopersAndroid 3.1 Platform ... New APIs for OpenGL ES 2.0, working with YUV image format, and ETC1 for texture ... ANY controller will work? (even non xbox)? - GameSpot.comI have a usb PC controller. I has all the necessary buttons (4 shoulder, 2 sticks which press in, etc). Should it work with this game?---What's the mafia's favorite game? 5/12/2012 4:44:19 AM
|