有没有办法确保被阻塞的线程以被阻止的顺序被唤醒?我在某处读到这将被称为"强锁",但我没有找到任何资源.
在Mac OS X上,可以设计一个FIFO队列来存储被阻塞线程的所有线程ID,然后使用nifty函数pthread_cond_signal_thread_np()唤醒一个特定线程 - 这显然是非标准和非可移植的.
我能想到的一种方法是使用一个类似的队列,并在unlock()此时向broadcast()所有线程发送一个并让它们检查哪一个是下一个.
但这会产生很多开销.
解决问题的方法是将packaged_task发送到队列并让它按顺序处理它们.但对我而言,这似乎更像是一种解决方案而非解决方案.
编辑:
正如评论所指出的,这个问题可能听起来无关紧要,因为原则上没有保证锁定尝试的顺序.
作为澄清:
我有一些我称之为ConditionLockQueue的东西,它与Cocoa库中的NSConditionLock类非常相似,但是它维护了一个被阻塞的线程的FIFO队列而不是一个或多或少的随机池.
基本上任何线程都可以"排队"(有或没有特定'条件'的要求 - 一个简单的整数值 - 要满足).然后将该线程放在队列上并阻塞,直到它成为满足条件的队列中最前面的元素.
这提供了一种非常灵活的同步方式,我发现它在我的程序中非常有用.
现在我真正需要的是一种唤醒具有特定id的特定线程的方法.
但这些问题几乎是相似的.
我有一个类只是将函数调用转发到另一个类,我希望能够std::invocable<>在我的转发类上使用。但由于某种原因失败了......这是我应该期待的吗?有没有办法解决它?
#include <type_traits>
#include <utility>
struct Foo {
constexpr int operator()( int i ) const {
return i;
}
};
struct ForwardToFoo {
template<class ...Args>
constexpr decltype(auto) operator()( Args &&...args ) const {
Foo foo;
return foo( std::forward<Args>( args )... );
}
};
int main( void ) {
// These work fine
static_assert( std::is_invocable_v<ForwardToFoo, int> == true );
static_assert( std::is_invocable_v<Foo, int> == true );
static_assert( std::is_invocable_v<Foo> == false );
// This causes a compile error
static_assert( std::is_invocable_v<ForwardToFoo> == …Run Code Online (Sandbox Code Playgroud) 以下代码无法在Mac OS X 10.6上编译; 它在stl_algobase.h中的"从[...]消息实例化"列表后面给出了一个错误.
#include <vector>
int main( void )
{
std::vector<int*> *v = new std::vector<int*>( 1, NULL );
return 0;
}
Run Code Online (Sandbox Code Playgroud)
为了使它编译,我必须放置一个显式的转换NULL,即替换它(int*)(NULL).
但这看起来有点尴尬,我怀疑它应该是非常必要的; 它还使我的源代码看起来很奇怪的结构和嵌套在命名空间等等的更长的类型名称.
编辑(错误信息):
/Developer/SDKs/MacOSX10.6.sdk/usr/include/c++/4.2.1/bits/stl_algobase.h: In static member function 'static _OutputIterator std::__fill_n<true>::fill_n(_OutputIterator, _Size, const _Tp&) [with _OutputIterator = int**, _Size = int, _Tp = int]':
/Developer/SDKs/MacOSX10.6.sdk/usr/include/c++/4.2.1/bits/stl_algobase.h:665: instantiated from '_OutputIterator std::fill_n(_OutputIterator, _Size, const _Tp&) [with _OutputIterator = int**, _Size = int, _Tp = int]'
/Developer/SDKs/MacOSX10.6.sdk/usr/include/c++/4.2.1/bits/stl_uninitialized.h:184: instantiated from 'void std::__uninitialized_fill_n_aux(_ForwardIterator, _Size, const _Tp&, std::__true_type) [with …Run Code Online (Sandbox Code Playgroud) 我即将为类似mathematica的语言编写一个解析器,并且已经发现,有时会调用我的精神语法来解析表达式的子部分.
即如果我要解析
a+b*c+d
Run Code Online (Sandbox Code Playgroud)
parse()在查询"+"符号时调用'b*c'部分会很方便.
使用同一个语法实例时可以这样做吗?(语法参数为'*this')
虽然我还不完全相信这是否是完成这项特定任务的最佳方式,但我发现这个问题相当有趣,因为我在文档中找不到任何内容.
如果我使用这种技术,我不应该依赖于类本地变量或全局变量.但我想知道它是否主要由精神设计所允许.
编辑:
我的语法实例如下:
class MyGrammar : public boost::spirit::qi::grammar<...>
{
/* a few rules. Some with local and/or inherited attributes */
MyGrammar( void )
{
/* assign all the rules, use a few 'on_error' statements */
// In one or two rules I would like to invoke parse(...,*this,...)
// on a subrange of the expression
}
}
Run Code Online (Sandbox Code Playgroud)
谢谢!
我试图熟悉c ++ 11的新内存排序概念,并相信我对它们有很好的把握,直到我偶然发现了自旋锁的这种实现:
#include <atomic>
namespace JayZ
{
namespace Tools
{
class SpinLock
{
private:
std::atomic_flag spin_lock;
public:
inline SpinLock( void ) : atomic_flag( ATOMIC_FLAG_INIT ) {}
inline void lock( void )
{
while( spin_lock.test_and_set( std::memory_order_acquire ) )
;
}
inline void unlock( void )
{
lock.clear( std::memory_order_release );
}
};
}
}
Run Code Online (Sandbox Code Playgroud)
例如,在http://en.cppreference.com/w/cpp/atomic/atomic_flag
和"并行行动"一书中提到了相同的内容.我也在SO的某处找到了它.
但我只是不明白它为什么会起作用!
想象一下,线程1调用lock(),test_and_set()返回0作为旧值 - >线程1获得锁定.
但随后线程2出现并尝试相同.现在因为没有发生"存储同步"(release,seq_cst_acq_rel),所以线程1的spin_lock存储应该是轻松的类型.
但是由此得出它不能与线程2的spin_lock读取同步.这应该使线程2能够从spin_lock读取值0,从而获得锁定.
我的错误在哪里?
这似乎是一个相当基本的事情,所以我正在寻找一个或多或少的简短,内置和易读的解决方案.
我设想的最短的事情就是
hana::unfold_left<hana::tuple_tag>( hana::int_c<n>, [] ( auto count ) {
return hana::if_( count == hana::int_c<0>, hana::nothing,
hana::just( hana::make_pair( count - hana::int_c<1>,
hana::type_c<T> ) ) );
} );
Run Code Online (Sandbox Code Playgroud)
这远非短暂和可读...
c++ metaprogramming template-meta-programming c++14 boost-hana
c++ ×6
c++11 ×2
atomic ×1
boost ×1
boost-hana ×1
boost-spirit ×1
c++14 ×1
c++17 ×1
locking ×1
macos ×1