我的信号量(来自Boost的named_semaphore)我做错了什么?

时间:2017-09-18 10:04:32

标签: c++ semaphore c++03 boost-interprocess

抽象

我提供了一个代码示例,用于复制我在软件中出现的一个非常奇怪的错误。它使用Boost创建3个命名信号量,并在单个线程中等待每个信号量。这有效。但是如果我改变信号量的名称(通过添加给定的前缀),它就不会:第3个信号量无缘无故地等待无限时间。

详细信息(源代码和行为)

#include <string>
#include <vector>
#include <iostream>
#include <boost/thread.hpp>
#include <boost/date_time.hpp>
#include <boost/interprocess/sync/named_semaphore.hpp>

struct Lock
{
    std::string name;
    unsigned int count;
    Lock(const std::string& name_, unsigned int count_) : name(name_), count(count_) {}
};

int main()
{
    std::vector<Lock> locks;
    locks.push_back(Lock("Sleep1", 1));
    locks.push_back(Lock("Hello", 1));
    locks.push_back(Lock("Sleep2", 1));

    for(std::size_t i = 0; i < locks.size(); ++i)
    {
        {
            const std::string sem_name = locks[i].name;
            const unsigned int sem_count = locks[i].count;
            std::cout << "Open or Create semaphore (" << sem_name << ", " << sem_count << ")" << std::endl;
            boost::interprocess::named_semaphore semaphore(boost::interprocess::open_or_create, sem_name.c_str(), sem_count);
            std::cout << "Wait..." << std::flush;
            semaphore.wait();
            std::cout << " DONE" << std::endl;
        }
        boost::this_thread::sleep(boost::posix_time::seconds(5));
        {
            const std::string sem_name = locks[i].name;
            std::cout << "Open semaphore (" << sem_name << ")" << std::endl;
            boost::interprocess::named_semaphore semaphore(boost::interprocess::open_only, sem_name.c_str());
            std::cout << "Post..." << std::flush;
            semaphore.post();
            std::cout << " DONE" << std::endl;
        }
    }

    return 0;
}

执行此示例,我得到以下(预期)输出:

> ./sem
Open or Create semaphore (Sleep1, 1)
Wait... DONE
Open semaphore (Sleep1)
Post... DONE
Open or Create semaphore (Hello, 1)
Wait... DONE
Open semaphore (Hello)
Post... DONE
Open or Create semaphore (Sleep2, 1)
Wait... DONE
Open semaphore (Sleep2)
Post... DONE

如果我用以下内容替换定义信号量名称的行:

std::vector<Lock> locks;
locks.push_back(Lock("CHAIN_EVALUATOR_Sleep1", 1));
locks.push_back(Lock("CHAIN_EVALUATOR_Hello", 1));
locks.push_back(Lock("CHAIN_EVALUATOR_Sleep2", 1));

执行不会以以下输出终止:

Open or Create semaphore (CHAIN_EVALUATOR_Sleep1, 1)
Wait... DONE
Open semaphore (CHAIN_EVALUATOR_Sleep1)
Post... DONE
Open or Create semaphore (CHAIN_EVALUATOR_Hello, 1)
Wait... DONE
Open semaphore (CHAIN_EVALUATOR_Hello)
Post... DONE
Open or Create semaphore (CHAIN_EVALUATOR_Sleep2, 1)
Wait...

请注意新名称的奇怪选择。实际上,它失败了。它不会因FOO_BAR_FOO_BAR_Sleep1而导致FOOBAR_FOOBAR_Sleep1失败。它看起来很奇怪,我想我没有正确使用它,而且我是一个随意的行为......

配置

  • Linux openSUSE 42.1
  • GCC 4.8.5
  • Boost 1.64.0(包括Boost.Python 用python 2.7.9)

编译专线

g++ test_semaphore.cpp -o sem \
-I /softs/boost/1.64.0/python/2.7.9/64/gcc/4.8.5/include \
/softs/boost/1.64.0/python/2.7.9/64/gcc/4.8.5/lib/libboost_date_time-mt.a \
/softs/boost/1.64.0/python/2.7.9/64/gcc/4.8.5/lib/libboost_thread-mt.a \
/softs/boost/1.64.0/python/2.7.9/64/gcc/4.8.5/lib/libboost_system-mt.a \
-l pthread

注意: 出于兼容性原因,我不使用C ++ 11。

1 个答案:

答案 0 :(得分:2)

Named semaphors in boost are implying Kernel or Filesystem persistence所以当您传递open_or_create时,可能存在具有指定名称的现有命名信号量(可能来自之前的中断启动?),在这种情况下,sem_count将被忽略,信号量将会处于离开的状态。尝试在创建或传递named_semaphore::remove标志之前调用create_only