user defined struct can't be passed through tid.send - multithreading

I have created a mutlithreaded simulator that relies heavily on the native message passing between threads (don't go telling me to go single threaded it's for my thesis on D and I need to get this to work)
after a very durty kludge involving a lot of casts of objects to and from shared. which prolly had some ugly race condition bugs. I decided to create an opaque type that represents an object that can receive messages that should be able to be passed around without all that casting...
no such luck
struct OpaqueFaseSim{
Tid tid;
void send(...){...}
}
void foo(){
Tid tid;
long time;
OpaqueFaseSim ofs;
//...
tid.send(ofs,time);//Error: static assert "Aliases to mutable thread-local data not allowed."
}
why can I pass a Tid around but not a struct containing only a Tid?
and how can I fix this

I think it's because Tid has a MessageBox field which is a class type.
You can type OpaqueFaseSim's tid field as shared or ___gshared and it will work:
struct OpaqueFaseSim{
Bar bar;
shared Tid tid;
// __gshared Tid tid;
}

Related

An Efficient Non-Enforcing, Verifying, Mutex

Class foo has a method bar. According to some synchronization protocol, the bar method of a specific foo object, will be only called by at most one thread at any point in time.
I'd like to add a very lightweight verification_mutex to verify this / debug synchronization abuses. It will be used similarly to a regular mutex:
class foo {
public:
void bar() {
std::lock_guard<verification_mutex> lk{m};
...
}
private:
mutable verification_mutex m;
};
however, it will not in itself necessarily lock or unlock anything. Rather, it will just throw if multithreaded simultaneous access is detected. The point is to make its runtime footprint as low as possible (including its effect on other code, e.g., through memory barriers).
Here are three options for implementing verification_mutex:
A wrapper around std::mutex, but with lock implemented by a check that trylock succeeded (this is just to get the idea; clearly not very fast)
An atomic variable noting the current "locking" thread id, with atomic exchange operations (see implementation sketch below).
Same as 2, but without atomics.
Are these correct or incorrect (in particular, 2 and esp. 3)? How will they affect performance (esp. of surrounding code)? Is there an altogether superior alternative?
Edit The answer by #SergeyA below is fine, but I'm in particular curious about the memory barriers. A solution not utilizing them would be great, as would be an answer giving some intuitive explanation why any solution omitting them would necessarily fail.
Implementation Sketch
#include <atomic>
#include <thread>
#include <functional>
class verification_mutex {
public:
verification_mutex() : m_holder{0}{}
void lock() {
if(m_holder.exchange(get_this_thread_id()) != 0)
throw std::logic_error("lock");
}
void unlock() {
if(m_holder.exchange(0) != get_this_thread_id())
throw std::logic_error("unlock");
}
bool try_lock() {
lock();
return true;
}
private:
static inline std::size_t get_this_thread_id() {
return std::hash<std::thread::id>()(std::this_thread::get_id());
}
private:
std::atomic_size_t m_holder;
};
Option 3 is not viable. You need a memory barrier when reading/writing a variable from multiple threads.
Of all options, atomic boolean variable would be the fastest, since it won't require context switches (mutexes might). Something like that:
class verifying_mutex {
std::atomic<bool> locked{false};
public:
bool lock() {
if (!locked.compare_exchange_strong(false, true))
throw std::runtime_error("Incorrect mt-access pattern");
}
bool unlock() {
locked = false;
}
};
On a side note, your original version of lock used thread_id, which would slow you down unnecessary. Do not do this.

Can't pass a local variable from a thread

I made a thread thread1 which creates another thread thread2. When I try to pass the value of fd (fd declared inside thread2) using pthread_exit from thread2 to thread1 I get a garbage value in retval. But when I declare fd as a global variable I get correct value in retval. I got an answer that this is because the thread is finished so it can't pass the value. But in case of functions, a local variable's scope is also limited inside the function and they do return values. So why can't a thread do that?
Here is the code that I tried:
void *thread2(void *message)
{
int fd;
void *retval;
fd=open(message,O_RDWR);
printf("message is - %s",(char *)message);
pthread_exit(&fd);
}
void *thread1(void *message)
{
void *retval;
pthread_t *tid2;
tido=malloc(sizeof(pthread_t));
pthread_create(tid2,NULL,thread2,message);
pthread_join(*tid2,&retval);
printf("fd in write is-%d\n",*(int *)retval);
pthread_exit(&retval);
}
Um... your int fd is an automatic variable (which we may assume is on the stack), so is out of scope when thread2() returns, so passing a pointer to fd out of the function is probably going to lead to disappointment.
A function can return the value of an automatic (aka local) variable. What it cannot do is return the address of one (not and work, anyway).
What you could do is construct a struct to pass into thread2(), to carry parameters in and results back.

starting std::thread with anonymous class call

I am curious as to how to correctly start a std::thread using an anonymous class call.
With the below code, if my class only having 1 member variable and I call std::thread td(someclass(shared_mutex)); I get a compiler warning of warning
C4930: 'std::thread td(someclass)': prototyped function not called (was a variable definition intended?)
However, if I add a second member variable as below and call it with
std::thread td(someclass(shared_mutex,x));
I get an error with error C2064: term does not evaluate to a function taking 0 arguments.
class someclass
{
private:
std::mutex& shared_mutex;
int x;
public:
someclass(std::mutex& init_mutex, int init_x) :
shared_mutex(init_mutex),
x(init_x)
{}
//...
};
int main()
{
std::mutex shared_mutex;
int x = 10;
std::thread td(someclass(shared_mutex,x));
td.join();
return 0;
}
The only way around this is by creating an
void operator()()
{}
within the class, but is that the correct method, just to have some kind of starting function for the thread reference or am I missing some other point here? I thought the constructor would be resolver for that?
Try using { and } syntax to construct your object to avoid veximg parses as a function declaration.
std::thread td(someclass(shared_mutex,x))
becomes
std::thread td{someclass{shared_mutex,x}}
It seems that you want your thread to execute the long-running constructor of someclass and then immediately discard the newly constructed someclass. This can be done by passing the thread constructor a function object that does just that:
int main()
{
std::mutex shared_mutex;
int x = 10;
std::thread td([&]{someclass(shared_mutex,x);});
td.join();
return 0;
}
Be warned: constructing a new thread is a hugely expensive operation, so you should avoid casually spawning new threads if you have the ability to instead reuse existing threads, unless you are only going to create new threads very infrequently.

C++11 When To Use A Memory Fence?

I'm writing some threaded C++11 code, and I'm not totally sure on when I need to use a memory fence or something. So here is basically what I'm doing:
class Worker
{
std::string arg1;
int arg2;
int arg3;
std::thread thread;
public:
Worker( std::string arg1, int arg2, int arg3 )
{
this->arg1 = arg1;
this->arg2 = arg2;
this->arg3 = arg3;
}
void DoWork()
{
this->thread = std::thread( &Worker::Work, this );
}
private:
Work()
{
// Do stuff with args
}
}
int main()
{
Worker worker( "some data", 1, 2 );
worker.DoWork();
// Wait for it to finish
return 0;
}
I was wondering, what steps do I need to take to make sure that the args are safe to access in the Work() function which runs on another thread. Is it enough that it's written in the constructor, and then the thread is created in a separate function? Or do I need a memory fence, and how do I make a memory fence to make sure all 3 args are written by the main thread, and then read by the Worker thread?
Thanks for any help!
The C++11 standard section 30.3.1.2 thread constructors [thread.thread.constr] p5 describes the constructor template <class F, class... Args> explicit thread(F&& f, Args&&... args):
Synchronization: the completion of the invocation of the constructor synchronizes with the beginning of the invocation of the copy of f.
So everything in the current thread happens before the thread function is called. You don't need to do anything special to ensure that the assignments to the Worker members are complete and will be visible to the new thread.
In general, you should never have to use a memory fence when writing multithreaded C++11: synchronization is built into mutexes/atomics and they handle any necessary fences for you. (Caveat: you are on your own if you use relaxed atomics.)

Question about pthreads & pointers

Here is an example of thread creation code that is often seen. pthread_create uses a lot of pointers/addresses and I was wondering why this is so.
pthread_t threads[NUM_THREADS];
long t;
for(t=0; t<NUM_THREADS; t++){
rc = pthread_create(&threads[t], NULL, &someMethod, (void *)t);
}
Is there a major advantage or difference for using the '&' to refer to the variable array 'threads' as well as 'someMethod' (as opposed to just 'threads' and just 'someMethod')? And also, why is 't' usually passed as a void pointer instead of just 't'?
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine)(void*), void *arg);
You need to pass a pointer to a pthread_t variable to pthread_create. &threads[t] and threads+t achieve this. threads[t] does not. pthread_create requires a pointer so it can return a value through it.
someMethod is a suitable expression for the third argument, since it's the address of the function. I think &someMethod is redundantly equivalent, but I'm not sure.
You are casting t to void * in order to jam a long into a void *. I don't think a long is guaranteed to fit in a void *. It's definitely a suboptimal solution even if the guarantee exists. You should be passing a pointer to t (&t, no cast required) for clarity and to ensure compatibility with the expected void *. Don't forget to adjust someMethod accordingly.
pthread_t threads[NUM_THREADS];
long t;
for (t=0; t<NUM_THREADS; t++) {
rc = pthread_create(&threads[t], NULL, someMethod, &t);
}

Resources