- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我已经实现了一个优先级从asio examples开始的任务队列和一个使用这个队列的定时器类。这是代码:
class handler_priority_queue
{
private:
class queued_handler{
private:
size_t _priority;
std::function<void()> _function;
public:
queued_handler(size_t p, std::function<void()> f): _priority(p), _function(f){}
friend bool operator<(const queued_handler& a, const queued_handler& b){
return a._priority < b._priority;
}
void operator()() {
_function();
}
};
std::priority_queue<queued_handler> _handlers;
public:
// A generic wrapper class for handlers to allow the invocation to be hooked.
template <typename Handler> class wrapped_handler
{
private:
handler_priority_queue& _queue;
size_t _priority;
Handler _handler;
public:
handler_priority_queue& queue() {return _queue;}
size_t priority() {return _priority;}
wrapped_handler(handler_priority_queue& q, size_t p, Handler h)
: _queue(q), _priority(p), _handler(h){}
template <typename ...Args>
void operator()(Args&&... args){
_handler(std::forward<Args>(args)...);
}
};
template <typename Handler> wrapped_handler<Handler> wrap(size_t priority, Handler handler){
return wrapped_handler<Handler>(*this, priority, handler);
}
void add(size_t priority, std::function<void()> function);
void execute_all();
void execute_one();
bool empty();
};
// Custom invocation hook for wrapped handlers.
template <typename Function, typename Handler>
void asio_handler_invoke(Function f, handler_priority_queue::wrapped_handler<Handler>* h){
h->queue().add(h->priority(), f);
std::cout<<"LLAMANDO AL INVOKE"<<std::endl; //BORRAR!!
}
class C_priority_task_queue{
private:
asio::io_service& _io;
handler_priority_queue _pri_queue;
public:
template <typename Handler> handler_priority_queue::wrapped_handler<Handler> wrap(int priority, Handler handler){
return _pri_queue.wrap(priority, handler);
}
explicit C_priority_task_queue(asio::io_service& io): _io(io){}
C_priority_task_queue(C_priority_task_queue const&) = delete;
C_priority_task_queue& operator =(C_priority_task_queue const&) = delete;
asio::io_service& io() {return _io;}
void run();
};
void handler_priority_queue::add(size_t priority, std::function<void()> function){
_handlers.push(queued_handler(priority, function));
}
void handler_priority_queue::execute_one(){
if(!_handlers.empty()){
queued_handler handler = _handlers.top();
handler();
_handlers.pop();
}
}
bool handler_priority_queue::empty(){
return _handlers.empty();
}
void C_priority_task_queue::run(){
while (_io.run_one())
{
_io.poll();
while(!_pri_queue.empty())
{
_io.poll();
_pri_queue.execute_one();
}
}
}
class C_timer {
private:
asio::high_resolution_timer _timer;
uint8_t _timer_id;
C_priority_task_queue& _prio_queue;
void timer_handler_internal(const asio::error_code& e, uint8_t timer_id, const uint64_t sched_time);
virtual void timer_handler(const uint64_t sched_time)=0;
public:
size_t _priority;
explicit C_timer(C_priority_task_queue& prio_queue, size_t priority);
virtual ~C_timer();
void set_timer(uint64_t sched_time);
int cancel();
};
C_timer::C_timer(C_priority_task_queue& prio_queue, size_t priority):
_timer(prio_queue.io()), _timer_id(0), _prio_queue(prio_queue), _priority(priority){}
C_timer::~C_timer(){}
void C_timer::set_timer(uint64_t sched_time){
++_timer_id;
_timer.expires_at(std::chrono::time_point<std::chrono::high_resolution_clock>(std::chrono::milliseconds(sched_time)));
_timer.async_wait(_prio_queue.wrap(_priority, std::bind(&C_timer::timer_handler_internal, this,
std::placeholders::_1/*error*/, _timer_id, sched_time)));
}
int C_timer::cancel(){
++_timer_id;
return _timer.cancel();
}
void C_timer::timer_handler_internal(const asio::error_code& e, uint8_t timer_id,
const uint64_t sched_time){
if(e==asio::error::operation_aborted || timer_id != _timer_id){
return;
}
timer_handler(sched_time);
}
class C_timer_test: public C_timer{
private:
int _period;
virtual void timer_handler(const uint64_t sched_time) override{
std::cout<<"timer fired"<<std::endl;
uint64_t current_time = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now().time_since_epoch()).count();
set_timer(current_time + _period);
}
public:
C_timer_test(C_priority_task_queue& prio_queue, int priority, int period):C_timer(prio_queue, priority), _periodo(period){}
virtual ~C_timer_test(){}
void run(uint64_t delay=0){
uint64_t time = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now().time_since_epoch()).count();
set_timer(time + delay);
}
};
问题是如果我执行这个:
int main()
{
asio::io_service io;
C_priority_task_queue prio_queue(io);
asio::io_service::work w(io);
C_timer_test ti1(prio_queue, 0, 2000);
ti1.run();
prio_queue.run();
return 0;
}
我遇到了段错误。
但是,如果我执行以下代码,它工作正常:
int main()
{
asio::io_service io;
C_priority_task_queue prio_queue(io);
asio::high_resolution_timer _timer1(io);
asio::io_service::work w(io);
C_timer_test ti1(prio_queue, 0, 2000);
ti1.run();
prio_queue.run();
return 0;
}
这两段代码之间的唯一区别是在第二个主要代码中,我添加了以下行 asio::high_resolution_timer _timer1(io);
我没有在任何地方使用过。
调试程序我发现这一行的信号正在上升: func_(&owner, this, ec, bytes_transferred);
在文件中 task_io_service_operation.hpp
我使用的是 asio 版本 1.10.6。
关于可能发生的事情有什么建议吗?
来自 gdb 的回溯:
gdb ./main
GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.2) 7.7.1
This GDB was configured as "i686-linux-gnu".
(gdb) r
[libthread_db enabled]
Using host libthread_db library "/lib/i386-linux-gnu/libthread_db.so.1".
Program received signal SIGSEGV, Segmentation fault.
0x0805f0d4 in ?? ()
(gdb) backtrace
#0 0x0805f0d4 in ?? ()
#1 0x080529fb in asio::detail::task_io_service::do_run_one (this=0x805f030, lock=..., this_thread=..., ec=...) at /src/cpp/external_lib/asio/include/asio/detail/impl/task_io_service.ipp:371
#2 0x080526ce in asio::detail::task_io_service::run_one (this=0x805f030, ec=...) at /src/cpp/external_lib/asio/include/asio/detail/impl/task_io_service.ipp:169
#3 0x08052c68 in asio::io_service::run_one (this=0xbffff08c) at /src/cpp/external_lib/asio/include/asio/impl/io_service.ipp:71
#4 0x08051f32 in C_priority_task_queue::run (this=0xbffff094) at priority_task_queue.cpp:19
#5 0x08049ac3 in main () at main.cpp:46
这里有 MakeFile:
TARGET=main
SOURCES= main.cpp base_timer.cpp priority_task_queue.cpp
SOURCE_DIR=.
INCLUDE_LIB= -L/src/cpp/libcore
INCLUDE_DIR=-I/src/cpp/external_lib/asio/include \
-I/src/cpp/libcore/include
INSTALL_DIR=.
LIB=-pthread
CXX=g++
CFLAGS=-Wall -fexceptions -fpermissive -std=c++11 -DASIO_STANDALONE
CFLAGS_DEBUG = -g3 -DDEBUG
OBJDIR_DEBUG=obj
BINDIR_DEBUG=.
OBJECTS_DEBUG:= $(addprefix $(OBJDIR_DEBUG)/,$(SOURCES:.cpp=.o))
all: debug
$(OBJDIR_DEBUG)/%.o: $(SOURCE_DIR)/%.cpp
@test -d $(OBJDIR_DEBUG) || mkdir -p $(OBJDIR_DEBUG)
$(CXX) $(CFLAGS) $(CFLAGS_DEBUG) $(INCLUDE_DIR) -c $< -o $@
debug: $(OBJECTS_DEBUG)
@test -d $(BINDIR_DEBUG) || mkdir -p $(BINDIR_DEBUG)
$(CXX) -o $(BINDIR_DEBUG)/$(TARGET) $^ $(INCLUDE_LIB) $(LIB)
根据我的调查,我发现如果我在 .h 中定义 base_timer 成员(基本上是 asio::high_resolution_timer)初始化,代码运行正常,但如果我在 .cpp 中这样做,代码崩溃。
我的意思是,
explicit C_timer(C_priority_task_queue& prio_queue, size_t priority):
_timer(prio_queue.io()), _timer_id(0), _prio_queue(prio_queue), _priority(priority){}
在 .h 中有效,但是
C_timer::C_timer(C_priority_task_queue& prio_queue, size_t priority):
_timer(prio_queue.io()), _timer_id(0), _prio_queue(prio_queue), _priority(priority){}
.cpp 失败
最佳答案
除了与 chrono(时间点或持续时间,选择一个!)的“不自然”杂耍之外,代码看起来还不错。我无法重现任何故障(GCC、Linux):
如果添加随机变量使问题出现/消失,您应该考虑未定义行为,使用静态分析、valgrind/purify/...和代码审查来找到您的罪魁祸首。 Valgrind、ASAN 和 UBSAN 在我的 PC 上运行干净
@sehe thanks for your effort. The diference is If I put every code into a single file, main.cpp, it runs, but if I separate into several files, the problem still there. In other hand, If I instanciate a high_resolution_timer object in the main.cpp, no matter the place (inside main(), in separate function that never is called, ...) it runs, but without it, a segmentation fault is raised.
太好了:您找到了 UB 的潜在来源:查看非 ODR 安全的静态变量或内联函数的使用。 (仔细检查所有翻译单元是否使用相同的编译器标志)。
此外,请记住 UB 是 UNDEFINED,所以就像添加一个不相关的 _timer1
改变明显的行为(不改变 UB 的 source)一样使其看起来有效。
它在我的机器上运行干净的事实告诉你这必须是特定于平台的 UB 源
关于c++ - async_wait 中的 asio high_resolution_timer 段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36038343/
我正在浏览 boost::asio 示例。我在看 Example 4 令人困惑的是,这个例子中的 WaitHandler 有签名 void print (this) 但是 async_wait 调用需
我有一些 lua 脚本有一些长时间运行的任务,比如获取网页,所以我让它 yield 然后 C 代码句柄获取页面作业异步,所以线程可以自由地做其他工作,并在指定时间后返回检查查看获取页面作业是否已完成,
我们有一个方法需要经常调用来做一些计算(大约每秒 20 次)。这是一个同步调用。调用者需要尽快得到结果。但该计算过程有时花费的时间比预期的要长。我们不想改变其他任何东西。我们只是想添加一种监控机制来标
这很好用: class cStartSequence { void Tick() { // do something } void Wait() { myTimer->expires_f
在打开的套接字上时,我调用async_read()/read(),对等方随后关闭套接字-我将在处理程序中收到eof错误,但是对于async_wait()/wait()不会发生,该处理程序调用时没有错误
我正在创建一个程序,并且我正在尽可能地异步执行。 我需要运行一个程序,当这个程序完成时它调用一个回调函数。我找到了一个版本的 boost::process 并决定使用,但似乎有示例但在我下载的源代码中
我正在学习 Boost.Asio,但我对 boost::asio::deadline_timer async_wai 有疑问。这是来自 boost 主页的代码: // // timer.cpp //
在我的应用程序中,我发送和接收大量消息并充当服务器。与此同时,我检查客户端的 session 超时。当我在我的应用程序中不使用 async_wait 时,我的程序运行良好。但是当我使用 async_w
我执行一个简单的例子作为测试,我想在 5 秒后执行一个简单的操作。我正在使用带有 async_wait 的 boost::deadline_timer,但是 async_wait 不是异步等待...这
我正在学习 boost asio 文档。我遇到了这个 deadline_timer 示例。 #include #include #include #include /*This timer e
boost asio deadline_timer async_wait 函数采用以下形式的处理程序: void handler(const boost::system::error_code& er
当我在方法 SendMessageAgain 中调用 deadline_timer::async_wait 时,偶尔会抛出段错误。它可以通过以下两种方式之一发生;我在下面包含了回溯。它似乎是随机的,这
这个问题在这里已经有了答案: How to use boost bind with a member function (3 个答案) 关闭 7 年前。 在这个类中使用 boost 异步定时器的例子
这个问题的灵感来自 boost asio 文档 (link) 中关于异步定时器的教程。代码略作修改,效果更明显。 有一个相关的问题,Multiple async_wait from a boost A
为什么将 lambda 传递给 asyn_wait() 需要 auto ... 参数,而传递函数不需要这样的东西(即只需要函数名就可以),如 timer.async_wait( &print ); i
我已经实现了一个优先级从asio examples开始的任务队列和一个使用这个队列的定时器类。这是代码: priority_task_queue.h class handler_priority_qu
我得到了 boost io_service在一个线程中运行,我想在客户端发生某个事件后 6 秒在该线程中触发回调,如果该客户端已经在运行,则重置该客户端的计时器。 我维护一个 unordered_ma
我目前正在尝试使用 Boost::Asio 创建一个服务器应用程序,它可以做两件简单的事情: 接受客户的传入连接 一旦客户端被接受,启动一个boost::asio::deadline_timer,它会
我想转这个电话: timer.async_wait(handler); 进入这个电话: func(handler); 所以我尝试使用 std::bind: #include #include #i
是否可以在同一个 boost::asio::deadline_timer 上多次调用 async_wait? 我的意思是像下面这样: t->expires_from_now(delay); t->as
我是一名优秀的程序员,十分优秀!