Skip to content

Commit 2893b89

Browse files
committed
修复执行std::function时同时可能覆写导致的bug
1 parent 8c2a2f2 commit 2893b89

File tree

3 files changed

+82
-6
lines changed

3 files changed

+82
-6
lines changed

src/Network/BufferSock.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ class BufferSock : public Buffer {
5353
class BufferList : public noncopyable {
5454
public:
5555
using Ptr = std::shared_ptr<BufferList>;
56-
using SendResult = std::function<void(const Buffer::Ptr &buffer, bool send_success)>;
56+
using SendResult = toolkit::function_safe<void(const Buffer::Ptr &buffer, bool send_success)>;
5757

5858
BufferList() = default;
5959
virtual ~BufferList() = default;

src/Network/Socket.h

+5-5
Original file line numberDiff line numberDiff line change
@@ -315,20 +315,20 @@ class Socket : public std::enable_shared_from_this<Socket>, public noncopyable,
315315
//接收数据回调 [AUTO-TRANSLATED:e3b7ff16]
316316
//Receive data callback
317317
using onReadCB = std::function<void(Buffer::Ptr &buf, struct sockaddr *addr, int addr_len)>;
318-
using onMultiReadCB = std::function<void(Buffer::Ptr *buf, struct sockaddr_storage *addr, size_t count)>;
318+
using onMultiReadCB = toolkit::function_safe<void(Buffer::Ptr *buf, struct sockaddr_storage *addr, size_t count)>;
319319

320320
//发生错误回调 [AUTO-TRANSLATED:d6897b99]
321321
//Error callback
322-
using onErrCB = std::function<void(const SockException &err)>;
322+
using onErrCB = toolkit::function_safe<void(const SockException &err)>;
323323
//tcp监听接收到连接请求 [AUTO-TRANSLATED:c4e1b206]
324324
//TCP listen receives a connection request
325-
using onAcceptCB = std::function<void(Socket::Ptr &sock, std::shared_ptr<void> &complete)>;
325+
using onAcceptCB = toolkit::function_safe<void(Socket::Ptr &sock, std::shared_ptr<void> &complete)>;
326326
//socket发送缓存清空事件,返回true代表下次继续监听该事件,否则停止 [AUTO-TRANSLATED:2dd1c036]
327327
//Socket send buffer is cleared event, returns true to continue listening for the event next time, otherwise stops
328-
using onFlush = std::function<bool()>;
328+
using onFlush = toolkit::function_safe<bool()>;
329329
//在接收到连接请求前,拦截Socket默认生成方式 [AUTO-TRANSLATED:2f07f268]
330330
//Intercept the default generation method of the Socket before receiving a connection request
331-
using onCreateSocket = std::function<Ptr(const EventPoller::Ptr &poller)>;
331+
using onCreateSocket = toolkit::function_safe<Ptr(const EventPoller::Ptr &poller)>;
332332
//发送buffer成功与否回调 [AUTO-TRANSLATED:4db5efb8]
333333
//Send buffer success or failure callback
334334
using onSendResult = BufferList::SendResult;

src/Util/util.h

+76
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include <atomic>
2222
#include <unordered_map>
2323
#include "function_traits.h"
24+
#include "onceToken.h"
2425
#if defined(_WIN32)
2526
#undef FD_SETSIZE
2627
//修改默认64为1024路 [AUTO-TRANSLATED:90567e14]
@@ -504,6 +505,81 @@ class AnyStorage : public std::unordered_map<std::string, Any> {
504505
using Ptr = std::shared_ptr<AnyStorage>;
505506
};
506507

508+
template <class R, class... ArgTypes>
509+
class function_safe;
510+
511+
template <typename R, typename... ArgTypes>
512+
class function_safe<R(ArgTypes...)> {
513+
public:
514+
using func = std::function<R(ArgTypes...)>;
515+
using this_type = function_safe<R(ArgTypes...)>;
516+
517+
template <class F>
518+
using enable_if_not_this = typename std::enable_if<!std::is_same<this_type, typename std::decay<F>::type>::value, typename std::decay<F>::type>::type;
519+
520+
R operator()(ArgTypes... args) const {
521+
onceToken token([&]() { _doing = true; checkUpdate(); }, [&]() { checkUpdate(); _doing = false; });
522+
if (!_impl) {
523+
throw std::invalid_argument("try to invoke a empty functional");
524+
}
525+
return _impl(std::forward<ArgTypes>(args)...);
526+
}
527+
528+
function_safe(std::nullptr_t) {
529+
update(func{});
530+
}
531+
532+
function_safe &operator=(std::nullptr_t) {
533+
update(func{});
534+
return *this;
535+
}
536+
537+
template <typename F, typename = enable_if_not_this<F>>
538+
function_safe(F &&f) {
539+
update(func { std::forward<F>(f) });
540+
}
541+
542+
template <typename F, typename = enable_if_not_this<F>>
543+
this_type &operator=(F &&f) {
544+
update(func { std::forward<F>(f) });
545+
return *this;
546+
}
547+
548+
function_safe() = default;
549+
function_safe(this_type &&) = default;
550+
function_safe(const this_type &) = default;
551+
this_type &operator=(this_type &&) = default;
552+
this_type &operator=(const this_type &) = default;
553+
554+
operator bool() const { return _update ? (bool)_tmp : (bool)_impl; }
555+
556+
private:
557+
void checkUpdate() const {
558+
if (_update) {
559+
_update = false;
560+
_impl = std::move(_tmp);
561+
}
562+
}
563+
void update(func in) {
564+
if (!_doing) {
565+
// 没在执行中,那么立即覆写
566+
_impl = std::move(in);
567+
_tmp = nullptr;
568+
_update = false;
569+
} else {
570+
// 正在执行中,延后覆写
571+
_tmp = in;
572+
_update = true;
573+
}
574+
}
575+
576+
private:
577+
mutable bool _update = false;
578+
mutable bool _doing = false;
579+
mutable func _tmp;
580+
mutable func _impl;
581+
};
582+
507583
} // namespace toolkit
508584

509585
#ifdef __cplusplus

0 commit comments

Comments
 (0)