Asked  6 Months ago    Answers:  5   Viewed   30 times

Is it true that C++0x will come without semaphores? There are already some questions on Stack Overflow regarding the use of semaphores. I use them (posix semaphores) all the time to let a thread wait for some event in another thread:

void thread0(...)
{
  doSomething0();

  event1.wait();

  ...
}

void thread1(...)
{
  doSomething1();

  event1.post();

  ...
}

If I would do that with a mutex:

void thread0(...)
{
  doSomething0();

  event1.lock(); event1.unlock();

  ...
}

void thread1(...)
{
  event1.lock();

  doSomethingth1();

  event1.unlock();

  ...
}

Problem: It's ugly and it's not guaranteed that thread1 locks the mutex first (Given that the same thread should lock and unlock a mutex, you also can't lock event1 before thread0 and thread1 started).

So since boost doesn't have semaphores either, what is the simplest way to achieve the above?

 Answers

98

You can easily build one from a mutex and a condition variable:

#include <mutex>
#include <condition_variable>

class semaphore {
    std::mutex mutex_;
    std::condition_variable condition_;
    unsigned long count_ = 0; // Initialized as locked.

public:
    void release() {
        std::lock_guard<decltype(mutex_)> lock(mutex_);
        ++count_;
        condition_.notify_one();
    }

    void acquire() {
        std::unique_lock<decltype(mutex_)> lock(mutex_);
        while(!count_) // Handle spurious wake-ups.
            condition_.wait(lock);
        --count_;
    }

    bool try_acquire() {
        std::lock_guard<decltype(mutex_)> lock(mutex_);
        if(count_) {
            --count_;
            return true;
        }
        return false;
    }
};
Tuesday, June 1, 2021
 
Jauco
answered 6 Months ago
81

I guess that using the synchronized(){} keyword would also not work since I want to synchronize file system access and not access to variables/objects.

Using synchronized can work. You are assuming that if you want to control access to object X from multiple threads, you must use synchronized on that object. You don't. You can use synchronized on any object, provided all the accesses use the same object.

In fact, it is often better to use a separate private lock object for synchronization, because it is then impossible for code outside the class to synchronize on the lock.

So , you might have something like this, with one instance for each shared file:

 public class SharedFile
 {
      private final File path;
      private final Object lock = new Object();

      public SharedFile(File path) {
         this.path = path;
      }

      public void process(.....) throws IOException {
         synchronized(lock) {
            try(InputStream = new FileInputStream(path)) {
               ....
            }
         }
      }
 }
Wednesday, August 4, 2021
 
Pachvarsh
answered 4 Months ago
66

Yes, using a std::mutex inside of a handler is perfectly fine. A strand is just a queue with a mutex in disguise after all.

Friday, August 13, 2021
 
MasterJoe
answered 4 Months ago
20

This is a bug of boost::asio 1.54.0

I found two similar threads on the internet:

  • this one.
  • and that one (on stack overflow).

There is also a bug report here.

I installed boost 1.53 and it is now working just fine.

Friday, August 27, 2021
 
freeMagee
answered 3 Months ago
11

The best approach (which makes as few changes in your code as possible) is to do like this:

public class ConnectionFactory{
    private static ConnectionFactory instance = new ConnectionFactory();

    public static ConnectionFactory getInstance(){
        return instance;
    }

    private ConnectionFactory(){
    }
}

As you can see, there is no real need in getInstance method now, so you can simplify the code to:

public class ConnectionFactory{
    public static final ConnectionFactory INSTANCE = new ConnectionFactory();

    private ConnectionFactory(){
    }
}

UPD about synchronization: the best way is synchronizing on a lock which is not visible to outer classes, i.e.:

public class ConnectionFactory{
    private static final Object lock = new Object();

    public static void doSmth() {
        synchronized (lock) {

           ...
        }
    }

    public static void doSmthElse() {
        synchronized (lock) {

           ...
        }
    }
}

There are many discussions about "why synchronizing on this is a bad idea" (like this one), I think that the same is actual for synchronizing on class.

Monday, October 11, 2021
 
RLH
answered 2 Months ago
RLH
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :
 
Share