Skip to content

Instantly share code, notes, and snippets.

@yohhoy
Last active August 29, 2015 14:06
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yohhoy/191757eaa0fe8dfa39e8 to your computer and use it in GitHub Desktop.
Save yohhoy/191757eaa0fe8dfa39e8 to your computer and use it in GitHub Desktop.
Dead-lock demonstration with condition_variable::notify_one()/pthread_cond_signal()
//
// Dead-lock demonstration with condition_variable::notify_one()
//
#include <utility>
#include <mutex>
#include <condition_variable>
template<typename T>
class mt_slot {
T slot_;
bool hold_ = false;
std::mutex mtx_;
std::condition_variable cv_;
public:
void put(T data)
{
std::unique_lock<std::mutex> lk(mtx_);
while (hold_)
cv_.wait(lk);
slot_ = std::move(data);
hold_ = true;
cv_.notify_one();
}
T get()
{
std::unique_lock<std::mutex> lk(mtx_);
while (!hold_)
cv_.wait(lk);
cv_.notify_one();
hold_ = false;
return std::move(slot_);
}
};
//----------------------------------------------------------
#include <memory> // make_unique(C++14)
#include <string>
#include <vector>
#include <iostream>
#include <thread>
typedef std::unique_ptr<std::string> Data;
int main()
{
mt_slot<Data> slot;
std::vector<std::thread> threads;
threads.emplace_back([&]{ // C1 thread
std::cout << "C1:" << *slot.get() << std::endl;
});
threads.emplace_back([&]{ // C2 thread
std::cout << "C2:" << *slot.get() << std::endl;
});
threads.emplace_back([&]{ // P1 thread
slot.put( std::make_unique<std::string>("hello") );
});
threads.emplace_back([&]{ // P2 thread
slot.put( std::make_unique<std::string>("world") );
});
for (auto& t : threads) t.join();
}
/*
* Dead-lock demonstration with pthread_cond_signal()
*/
#include <pthread.h>
typedef char* T;
typedef struct mt_slot {
T slot;
int hold;
pthread_mutex_t mtx;
pthread_cond_t cv;
} mt_slot;
void slot_init(mt_slot* self)
{
self->hold = 0;
pthread_mutex_init(&self->mtx, NULL);
pthread_cond_init(&self->cv, NULL);
}
void slot_destroy(mt_slot* self)
{
pthread_mutex_destroy(&self->mtx);
pthread_cond_destroy(&self->cv);
}
void slot_put(mt_slot* self, T data)
{
pthread_mutex_lock(&self->mtx);
while (self->hold)
pthread_cond_wait(&self->cv, &self->mtx);
self->slot = data;
self->hold = 1;
pthread_cond_signal(&self->cv);
pthread_mutex_unlock(&self->mtx);
}
T slot_get(mt_slot* self)
{
T ret;
pthread_mutex_lock(&self->mtx);
while (!self->hold)
pthread_cond_wait(&self->cv, &self->mtx);
ret = self->slot;
self->hold = 0;
pthread_cond_signal(&self->cv);
pthread_mutex_unlock(&self->mtx);
return ret;
}
/*----------------------------------------------------------*/
#include <stdio.h>
mt_slot slot;
void* producer_thread(void* p)
{
slot_put(&slot, p);
return NULL;
}
void* consumer_thread(void *p)
{
printf("%s:%s¥n", (const char*)p, slot_get(&slot));
return NULL;
}
int main()
{
pthread_t c1, c2, p1, p2;
slot_init(&slot);
pthread_create(&c1, NULL, consumer_thread, "C1");
pthread_create(&c2, NULL, consumer_thread, "C2");
pthread_create(&p1, NULL, producer_thread, "hello");
pthread_create(&p2, NULL, producer_thread, "world");
pthread_join(c1, NULL);
pthread_join(c2, NULL);
pthread_join(p1, NULL);
pthread_join(p2, NULL);
slot_destroy(&slot);
}
@yohhoy
Copy link
Author

yohhoy commented Oct 1, 2014

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment