Skip to content

Commit 5fb3654

Browse files
committed
feat(flow): 1.12.12, 添加ExecuteInThreadAction动作。优化ExecuteCmdAction动作
1 parent c942414 commit 5fb3654

File tree

8 files changed

+286
-8
lines changed

8 files changed

+286
-8
lines changed

modules/flow/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ set(TBOX_FLOW_SOURCES
5050
actions/dummy_action.cpp
5151
actions/switch_action.cpp
5252
actions/execute_cmd_action.cpp
53+
actions/execute_in_thread_action.cpp
5354
to_graphviz.cpp)
5455

5556
set(TBOX_FLOW_TEST_SOURCES
@@ -71,6 +72,8 @@ set(TBOX_FLOW_TEST_SOURCES
7172
actions/wrapper_action_test.cpp
7273
actions/succ_fail_action_test.cpp
7374
actions/switch_action_test.cpp
75+
actions/execute_cmd_action_test.cpp
76+
actions/execute_in_thread_action_test.cpp
7477
to_graphviz_test.cpp)
7578

7679
add_library(${TBOX_LIBRARY_NAME} ${TBOX_BUILD_LIB_TYPE} ${TBOX_FLOW_SOURCES})
@@ -132,6 +135,7 @@ install(
132135
actions/dummy_action.h
133136
actions/switch_action.h
134137
actions/execute_cmd_action.h
138+
actions/execute_in_thread_action.h
135139
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/tbox/flow/actions
136140
)
137141

modules/flow/Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ HEAD_FILES = \
5050
actions/dummy_action.h \
5151
actions/switch_action.h \
5252
actions/execute_cmd_action.h \
53+
actions/execute_in_thread_action.h \
5354
to_graphviz.h \
5455

5556
CPP_SRC_FILES = \
@@ -73,6 +74,7 @@ CPP_SRC_FILES = \
7374
actions/dummy_action.cpp \
7475
actions/switch_action.cpp \
7576
actions/execute_cmd_action.cpp \
77+
actions/execute_in_thread_action.cpp \
7678
to_graphviz.cpp \
7779

7880
CXXFLAGS := -DMODULE_ID='"tbox.flow"' $(CXXFLAGS)
@@ -98,6 +100,7 @@ TEST_CPP_SRC_FILES = \
98100
actions/succ_fail_action_test.cpp \
99101
actions/switch_action_test.cpp \
100102
actions/execute_cmd_action_test.cpp \
103+
actions/execute_in_thread_action_test.cpp \
101104
to_graphviz_test.cpp \
102105

103106
TEST_LDFLAGS := $(LDFLAGS) -ltbox_flow -ltbox_eventx -ltbox_event -ltbox_util -ltbox_base -ldl

modules/flow/actions/execute_cmd_action.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,27 +69,27 @@ void ExecuteCmdAction::onStart() {
6969
);
7070

7171
} else {
72-
LogWarn("cmd is empty");
72+
LogWarn("action %d:%s[%s] cmd is empty", id(), type().c_str(), label().c_str());
7373
finish(false);
7474
}
7575
}
7676

7777
void ExecuteCmdAction::onStop() {
7878
auto result = thread_executor_.cancel(task_token_);
7979
if (result != eventx::ThreadExecutor::CancelResult::kExecuting)
80-
LogWarn("stop fail, cmd: '%s'", cmd_.c_str());
80+
LogWarn("action %d:%s[%s] stop fail, cmd: '%s'", id(), type().c_str(), label().c_str(), cmd_.c_str());
8181

8282
Action::onStop();
8383
}
8484

8585
void ExecuteCmdAction::onPause() {
86-
LogWarn("can't pause");
86+
LogWarn("action %d:%s[%s] can't pause", id(), type().c_str(), label().c_str());
8787
Action::onPause();
8888
}
8989

9090
void ExecuteCmdAction::onResume() {
9191
Action::onResume();
92-
LogWarn("can't pause");
92+
LogWarn("action %d:%s[%s] can't resume", id(), type().c_str(), label().c_str());
9393
}
9494

9595
void ExecuteCmdAction::onReset() {

modules/flow/actions/execute_cmd_action.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@
1717
* project authors may be found in the CONTRIBUTORS.md file in the root
1818
* of the source tree.
1919
*/
20-
#ifndef TBOX_FLOW_EXECUTE_CMD_ACTION_H_20241107
21-
#define TBOX_FLOW_EXECUTE_CMD_ACTION_H_20241107
20+
#ifndef TBOX_FLOW_EXECUTE_CMD_ACTION_H_20250526
21+
#define TBOX_FLOW_EXECUTE_CMD_ACTION_H_20250526
2222

2323
#include "../action.h"
2424

@@ -63,4 +63,4 @@ class ExecuteCmdAction : public Action {
6363
}
6464
}
6565

66-
#endif //TBOX_FLOW_EXECUTE_CMD_ACTION_H_20241107
66+
#endif //TBOX_FLOW_EXECUTE_CMD_ACTION_H_20250526
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
/*
2+
* .============.
3+
* // M A K E / \
4+
* // C++ DEV / \
5+
* // E A S Y / \/ \
6+
* ++ ----------. \/\ .
7+
* \\ \ \ /\ /
8+
* \\ \ \ /
9+
* \\ \ \ /
10+
* -============'
11+
*
12+
* Copyright (c) 2025 Hevake and contributors, all rights reserved.
13+
*
14+
* This file is part of cpp-tbox (https://github.com/cpp-main/cpp-tbox)
15+
* Use of this source code is governed by MIT license that can be found
16+
* in the LICENSE file in the root of the source tree. All contributing
17+
* project authors may be found in the CONTRIBUTORS.md file in the root
18+
* of the source tree.
19+
*/
20+
21+
#include "execute_in_thread_action.h"
22+
23+
#include <tbox/base/log.h>
24+
#include <tbox/base/lifetime_tag.hpp>
25+
#include <tbox/base/json.hpp>
26+
#include <tbox/util/execute_cmd.h>
27+
28+
namespace tbox {
29+
namespace flow {
30+
31+
ExecuteInThreadAction::ExecuteInThreadAction(event::Loop &loop, eventx::ThreadExecutor &thread_executor)
32+
: Action(loop, "ExecuteInThread")
33+
, thread_executor_(thread_executor)
34+
{ }
35+
36+
ExecuteInThreadAction::ExecuteInThreadAction(event::Loop &loop, eventx::ThreadExecutor &thread_executor, Func &&func)
37+
: Action(loop, "ExecuteInThread")
38+
, thread_executor_(thread_executor)
39+
, func_(std::move(func))
40+
{ }
41+
42+
void ExecuteInThreadAction::onStart() {
43+
Action::onStart();
44+
45+
if (func_) {
46+
struct Tmp {
47+
Func func;
48+
bool succ;
49+
Reason reason;
50+
};
51+
auto tmp = std::make_shared<Tmp>();
52+
tmp->func = func_;
53+
54+
auto ltw = ltt_.get();
55+
task_token_ = thread_executor_.execute(
56+
[tmp] {
57+
tmp->succ = tmp->func(tmp->reason);
58+
},
59+
[this, tmp, ltw] {
60+
if (ltw) {
61+
finish(tmp->succ, tmp->reason);
62+
} else {
63+
LogWarn("ExecuteInThreadAction object lifetime end");
64+
}
65+
}
66+
);
67+
68+
} else {
69+
LogWarn("cmd is empty");
70+
finish(false);
71+
}
72+
}
73+
74+
void ExecuteInThreadAction::onStop() {
75+
auto result = thread_executor_.cancel(task_token_);
76+
if (result != eventx::ThreadExecutor::CancelResult::kExecuting)
77+
LogWarn("action %d:%s[%s] stop fail", id(), type().c_str(), label().c_str());
78+
79+
Action::onStop();
80+
}
81+
82+
void ExecuteInThreadAction::onPause() {
83+
LogWarn("action %d:%s[%s] can't pause", id(), type().c_str(), label().c_str());
84+
Action::onPause();
85+
}
86+
87+
void ExecuteInThreadAction::onResume() {
88+
Action::onResume();
89+
LogWarn("action %d:%s[%s] can't resume", id(), type().c_str(), label().c_str());
90+
}
91+
92+
void ExecuteInThreadAction::onReset() {
93+
task_token_.reset();
94+
Action::onReset();
95+
}
96+
97+
void ExecuteInThreadAction::toJson(Json &js) const {
98+
Action::toJson(js);
99+
100+
js["task_token"] = task_token_.id();
101+
}
102+
103+
}
104+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*
2+
* .============.
3+
* // M A K E / \
4+
* // C++ DEV / \
5+
* // E A S Y / \/ \
6+
* ++ ----------. \/\ .
7+
* \\ \ \ /\ /
8+
* \\ \ \ /
9+
* \\ \ \ /
10+
* -============'
11+
*
12+
* Copyright (c) 2025 Hevake and contributors, all rights reserved.
13+
*
14+
* This file is part of cpp-tbox (https://github.com/cpp-main/cpp-tbox)
15+
* Use of this source code is governed by MIT license that can be found
16+
* in the LICENSE file in the root of the source tree. All contributing
17+
* project authors may be found in the CONTRIBUTORS.md file in the root
18+
* of the source tree.
19+
*/
20+
#ifndef TBOX_FLOW_EXECUTE_IN_THREAD_ACTION_H_20250527
21+
#define TBOX_FLOW_EXECUTE_IN_THREAD_ACTION_H_20250527
22+
23+
#include "../action.h"
24+
25+
#include <tbox/base/lifetime_tag.hpp>
26+
#include <tbox/eventx/thread_executor.h>
27+
28+
namespace tbox {
29+
namespace flow {
30+
31+
//! 在子线程中执行指定的动作
32+
class ExecuteInThreadAction : public Action {
33+
public:
34+
using Func = std::function<bool(Reason &)>;
35+
36+
explicit ExecuteInThreadAction(event::Loop &loop, eventx::ThreadExecutor &thread_executor);
37+
explicit ExecuteInThreadAction(event::Loop &loop, eventx::ThreadExecutor &thread_executor, Func &&func);
38+
39+
inline void setFunc(Func &&func) { func_ = std::move(func); }
40+
41+
virtual bool isReady() const { return bool(func_); }
42+
43+
protected:
44+
virtual void onStart() override;
45+
virtual void onStop() override;
46+
virtual void onPause() override;
47+
virtual void onResume() override;
48+
virtual void onReset() override;
49+
50+
virtual void toJson(Json &js) const override;
51+
52+
private:
53+
LifetimeTag ltt_;
54+
eventx::ThreadExecutor &thread_executor_;
55+
Func func_;
56+
57+
tbox::eventx::ThreadExecutor::TaskToken task_token_;
58+
};
59+
60+
}
61+
}
62+
63+
#endif //TBOX_FLOW_EXECUTE_IN_THREAD_ACTION_H_20250527
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
/*
2+
* .============.
3+
* // M A K E / \
4+
* // C++ DEV / \
5+
* // E A S Y / \/ \
6+
* ++ ----------. \/\ .
7+
* \\ \ \ /\ /
8+
* \\ \ \ /
9+
* \\ \ \ /
10+
* -============'
11+
*
12+
* Copyright (c) 2025 Hevake and contributors, all rights reserved.
13+
*
14+
* This file is part of cpp-tbox (https://github.com/cpp-main/cpp-tbox)
15+
* Use of this source code is governed by MIT license that can be found
16+
* in the LICENSE file in the root of the source tree. All contributing
17+
* project authors may be found in the CONTRIBUTORS.md file in the root
18+
* of the source tree.
19+
*/
20+
#include <gtest/gtest.h>
21+
#include <tbox/event/loop.h>
22+
#include <tbox/base/scope_exit.hpp>
23+
#include <tbox/eventx/work_thread.h>
24+
25+
#include "execute_in_thread_action.h"
26+
27+
namespace tbox {
28+
namespace flow {
29+
30+
TEST(ExecuteInThreadAction, IsReady) {
31+
auto loop = event::Loop::New();
32+
SetScopeExitAction([loop] { delete loop; });
33+
eventx::WorkThread worker(loop);
34+
35+
ExecuteInThreadAction action(*loop, worker);
36+
EXPECT_FALSE(action.isReady());
37+
38+
action.setFunc([] (Action::Reason &) { return true; });
39+
EXPECT_TRUE(action.isReady());
40+
}
41+
42+
TEST(ExecuteInThreadAction, Succ) {
43+
auto loop = event::Loop::New();
44+
SetScopeExitAction([loop] { delete loop; });
45+
eventx::WorkThread worker(loop);
46+
47+
ExecuteInThreadAction action(*loop, worker);
48+
action.setFunc(
49+
[] (Action::Reason &) {
50+
return true;
51+
}
52+
);
53+
54+
bool is_callback = false;
55+
action.setFinishCallback(
56+
[&] (bool is_succ, const Action::Reason &r, const Action::Trace &) {
57+
EXPECT_TRUE(is_succ);
58+
EXPECT_EQ(r.code, 0);
59+
60+
is_callback = true;
61+
loop->exitLoop();
62+
}
63+
);
64+
65+
EXPECT_TRUE(action.isReady());
66+
action.start();
67+
68+
loop->runLoop();
69+
EXPECT_TRUE(is_callback);
70+
}
71+
72+
TEST(ExecuteInThreadAction, Fail) {
73+
auto loop = event::Loop::New();
74+
SetScopeExitAction([loop] { delete loop; });
75+
eventx::WorkThread worker(loop);
76+
77+
ExecuteInThreadAction action(*loop, worker);
78+
action.setFunc(
79+
[] (Action::Reason &r) {
80+
r.code = 101;
81+
return false;
82+
}
83+
);
84+
85+
bool is_callback = false;
86+
action.setFinishCallback(
87+
[&] (bool is_succ, const Action::Reason &r, const Action::Trace &) {
88+
EXPECT_FALSE(is_succ);
89+
EXPECT_EQ(r.code, 101);
90+
91+
is_callback = true;
92+
loop->exitLoop();
93+
}
94+
);
95+
96+
EXPECT_TRUE(action.isReady());
97+
action.start();
98+
99+
loop->runLoop();
100+
EXPECT_TRUE(is_callback);
101+
}
102+
103+
}
104+
}

version.mk

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,4 @@
2121
# TBOX版本号
2222
TBOX_VERSION_MAJOR := 1
2323
TBOX_VERSION_MINOR := 12
24-
TBOX_VERSION_REVISION := 11
24+
TBOX_VERSION_REVISION := 12

0 commit comments

Comments
 (0)