Sign in to follow this  

problem with pthread

This topic is 3664 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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!

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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?

Share this post


Link to post
Share on other sites
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 :)

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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)?

Share this post


Link to post
Share on other sites
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!

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites

This topic is 3664 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this