problem with pthread

Started by
8 comments, last by the_edd 16 years, 4 months ago
Hi, Don't know why, but I can't get a simple program using pthreads working on Unix. Here's my uber simple code:

void *test()
{
	printf("INSIDE!!!\n");
	pthread_exit(NULL);
}

main()
{
	pthread_t thread;

        if(pthread_create(&thread, NULL, test, NULL) != 0)
               perror("Thread Ops!");
}

However, this runs, but doesn't print anything! Any ideas what could be wrong? Thank you!
Advertisement
As soon as the pthread_create function in main has completed, main exits - ending the process and all threads within it.

You need to wait for your thread to finish before leaving main. IIRC, this is done with pthread_join.
Quote:Original post by bakery2k1
As soon as the pthread_create function in main has completed, main exits - ending the process and all threads within it.

You need to wait for your thread to finish before leaving main. IIRC, this is done with pthread_join.


Ok, that would work. but imagine my thread has a while(1) inside it... How would that work?

thanks again
You'll need to modify your loop so that it says while(keep_going) instead. The other thread can change the value of keep_going before it attempts to join. You will need to make sure the appropriate synchronisation scaffolding is used around reads and writes to keep_going, however.
Quote:Original post by the_edd
You'll need to modify your loop so that it says while(keep_going) instead. The other thread can change the value of keep_going before it attempts to join. You will need to make sure the appropriate synchronisation scaffolding is used around reads and writes to keep_going, however.


But that would remove the purpose I want to give to the threads in my app... but I guess what I want can't be done with user-mode threads.
My main thread will be always listening for user console input. My other thread will have a while(1) where its dispatching and receiving messages thru udp.
Any more ideas?
Quote:Original post by jjoi
Quote:Original post by the_edd
You'll need to modify your loop so that it says while(keep_going) instead. The other thread can change the value of keep_going before it attempts to join. You will need to make sure the appropriate synchronisation scaffolding is used around reads and writes to keep_going, however.


But that would remove the purpose I want to give to the threads in my app... but I guess what I want can't be done with user-mode threads.
My main thread will be always listening for user console input. My other thread will have a while(1) where its dispatching and receiving messages thru udp.
Any more ideas?


You've completely lost me, sorry. What's wrong with this (in pseudo-C):

mutex g_lock;bool g_keep_going = true;bool keep_going(){    g_lock.acquire();    bool ret = g_keep_going;    g_lock.release();    return ret;}void udp_thread(){    while (keep_going())    {        data = read_stuff_from_network();        // etc...    }    }main(){    thread t(respond_to_udp);    t.start();    string s;    while( (cin >> s) && s != "stop")    {        // do stuff with s        // ...    }    g_lock.acquire()    g_keep_going = false;    g_lock.release();    t.join();}


Is this not sufficient?

I'd prefer to use a scoped-locking mechanism, but I don't want to confuse with that if you're using C. Also the globals are just for ease of exposition, here :)
Quote:Original post by the_edd
Quote:Original post by jjoi
Quote:Original post by the_edd
You'll need to modify your loop so that it says while(keep_going) instead. The other thread can change the value of keep_going before it attempts to join. You will need to make sure the appropriate synchronisation scaffolding is used around reads and writes to keep_going, however.


But that would remove the purpose I want to give to the threads in my app... but I guess what I want can't be done with user-mode threads.
My main thread will be always listening for user console input. My other thread will have a while(1) where its dispatching and receiving messages thru udp.
Any more ideas?


You've completely lost me, sorry. What's wrong with this (in pseudo-C):

*** Source Snippet Removed ***

Is this not sufficient?

I'd prefer to use a scoped-locking mechanism, but I don't want to confuse with that if you're using C. Also the globals are just for ease of exposition, here :)


Hmm, I see. However, I can't seem to port this to my situation.
This is what i have:

My library:
my_create(){	// Initialize stuff		create_thread(t, udp_stuff);	t.start();		// Some more initialization}my_send(){	// Add stuff to send list}my_receive(){	// Add stuff to receive list}udp_stuff(){	while(1)	{		// Mess with send and receive list				// Do udp sends and receives	}}



My main:
main(){	my_create();		my_send();		my_receive();}



However, running this, my app gets stuck in the while(1) of udp_stuff... where are my time slices??

Thanks again
There's not enough context in your example to diagnose it.

I assume the sending and receiving is adequately synchronized (probably using condition variables for a producer/consumer style pattern)?

Can you post a small program that exhibits the behaviour (or lack thereof)?
Quote:Original post by the_edd
There's not enough context in your example to diagnose it.

I assume the sending and receiving is adequately synchronized (probably using condition variables for a producer/consumer style pattern)?

Can you post a small program that exhibits the behaviour (or lack thereof)?


I'm building a reliable layer over UDP, where my_send and my_receive would replace the sendto and recvfrom.
my_send and my_receive will only add packets to a send_list and extract data from the first packet on the receive list, respectively.
handle_packets will check to see if those lists aren't empty, and if they're not, send/receive, reliably, those packets.
An example program using this library would be:

int main(){       int sock;       sock = create_socket(...);       struct sockaddr *host;       host = create_host(...);       // Data to send       char data[1024];       data = "blablablabla";      // Data to receive      char buf[1024];       my_connection *con = my_create(sock, host);       my_send(con, data);       if(my_receive(con, buf))              // Do something with buf}



thanks again!
Ok, so you actually want three threads in total here including the main one, if I understand your problem.

One thread loops processing data as it comes and effectively generates send and receive commands that go in to two different(?) queues. You would then have a thread processing each queue.

This would be set up along the following lines:

template<typename Data>class work_queue{    public:        typedef Data data;        typedef boost::function<void (const data &)> callback;        work_pool(const callback &cb) :             cb_(cb),            keep_going_(true),            thread_(boost::bind(&work_queue::process_q, this))        {        }        ~work_queue()        {            boost::mutex::scoped_lock lock(mtx_);            keep_going_ = false;            full_.notify();            thread_.join();        }        void add(const data &d)        {            boost::mutex::scoped_lock lock(mtx_);            q_.push(d);            full_.notify();        }    private:        data pluck_next()        {            assert(!q_.empty());            data ret(q_.front());            q_.pop();            return ret;        }        void process_q()        {            boost::mutex::scoped_lock lock(mtx_);            while(keep_going_)            {                while (q_.empty() && keep_going_) full_.wait(lock);                 try { if (keep_going_) callback_(pluck_next()); }                catch(const std::exception &ex) { std::cerr << "oops: " << ex.what() << '\n'; }                catch(...) { std::cerr << "oops: unknown exception thrown\n";            }        }    private:        callback cb_;        bool keep_going_;        boost::thread thread_;        std::queue<data> q_;        boost::mutex mtx_;        boost::condition full_;};void my_send(connection &conn, const send_data &data){    // ...}void my_recv(connection &conn, const recv_data &data){   // ...}int main(){    using namespace boost;    connection conn("localhost", 8080); // or whatever    work_queue<send_data> send_q(bind(&my_send, ref(conn), _1));    work_queue<recv_data> recv_q(bind(&my_recv, ref(conn), _1));    std::string s;    while ((std::cin >> s) && s != "stop")    {        // read from conn etc        // call send_q.add() and recv_q.add() as necessary        // and those queues will churn through the data    }    // the destructors of send_q and recv_q will shut them down correctly.}


I haven't compiled or checked this code, but I believe it to be correct modulo typos and "little mistakes". The key is with the condition variable in the work_queue<> class. Note that even though I've only used one thread per queue, it could easily be extended to work with an arbitrary number.

I've used boost because it makes this kind of thing much easier. Boost threads aren't too far away from pthreads, really. If you need any further explanation let me know.

This topic is closed to new replies.

Advertisement