由于前面对线程不太了解,这几天要写插件管理框架。由于每个插件加载进来后必须起线程,让每个插件单独运行在一个线程内,才能保证所有插件都能并行执行,否则前面的线程执行完后面的才能执行,会造成阻塞。所以调研了一大堆资料,最后实现了在类内部启动线程执行用户逻辑。
最后将实现的所有代码和配置贴到这里,以供后面参考。
a.h定义了基类,纯虚函数,没有对应的cpp文件。
#ifndef __H_A_H__
#define __H_A_H__
#include <iostream>
#include <stdio.h>
#include <unistd.h>
#include <thread>
namespace xxx_label_gen{
using namespace std;
class Parent
{
public:
int i;
std::thread t;
public:
virtual void print() { }
virtual void startThread(){}
virtual void createThread(){}
virtual void setI(int j){}
virtual int getI(){}
};
}
#endif
b.h和c.h是子类,各增加了一个成员变量和对应的函数,都有对应的cpp文件,在cpp文件中声明为插件(如果是单独测试线程,则可以不注册成插件,把class_loader相关的内容删掉)。
//b.h
#ifndef __H_B_H__
#define __H_B_H__
#include "a.h"
#include "class_loader/class_loader.h"
//class_loader/class_loader.h >
#include <random>
namespace xxx_label_gen{
using namespace std;
class Child : public Parent
{
int j;
public:
void print()
{
cout<<"class Child"<<endl;
}
void createThread();
void startThread();
int getJ();
void setJ(int k);
int getI();
void setI(int s);
};
}
#endif
//c.h
#ifndef __H_C_H__
#define __H_C_H__
#include "a.h"
#include <random>
#include "class_loader/class_loader.h"
namespace xxx_label_gen{
using namespace std;
class Child2 : public Parent
{
int k;
public:
void print()
{
cout<<"class Child2"<<endl;
}
// void createThread(void *arg);
void createThread();
void startThread();
int getK();
void setK(int k);
int getI();
void setI(int s);
};
}
#endif
//b.cpp
#include "b.h"
namespace xxx_label_gen{
/*
void Child::createThread(void *arg){
Child * tmp = (Child*) arg;
while(tmp->getI()!=1){
sleep(2);
tmp->setJ(random());
printf("j=%d\n",tmp->getJ());
}
}*/
void Child::createThread(){
// Child * tmp = (Child*) arg;
printf("in the child::createThread(), and i =%d\n",i);
while(i!=1){
sleep(2);
j = random();//修改Child的public类型的成员变量j
printf("j=%d\n",j);
}
printf("in the end of the child::createThread()\n");
}
void Child::startThread(){
//t = new std::thread(&createThread,this);
i = 50;
printf("in the child::startThread()!\n");
t = std::thread(&Child::createThread,this);
t.detach();
/* 这段代码会造成createThread()一直在执行,在调用该函数的地方的后续代码都无法执行,所以这里不能使用while()
while(i--){
sleep(2);
printf("current j=%d\n",j);
}
*/
/*if(t.joinable()) t.detach();
while(i--){
sleep(1);
}
sleep(5);*/
}
void Child::setI(int j)
{
i = j;
}
int Child::getI(){
return i;
}
void Child::setJ(int k)
{
j = k;
}
int Child::getJ(){
return j;
}
}
CLASS_LOADER_REGISTER_CLASS(xxx_label_gen::Child, xxx_label_gen::Parent)
#include "c.h"
CLASS_LOADER_REGISTER_CLASS(xxx_label_gen::Child2, xxx_label_gen::Parent)//不制作插件的话,删掉上面的句子
namespace xxx_label_gen{
/*
void Child2::createThread(void *arg){
Child2 * tmp = (Child2*) arg;
while(tmp->getI()!=1){
sleep(3);
tmp->setK(random());
printf("k=%d\n",tmp->getK());
}
}*/
void Child2::createThread(){
//Child2 * tmp = (Child2*) arg;
while(i!=1){
sleep(3);
k = random();//修改Child2的public类型的成员变量k
printf("k=%d\n",k);
}
}
void Child2::startThread(){
i = 100;
t = std::thread(&Child2::createThread,this);
t.detach();
//if(t.joinable()) t.detach();
/* 这段代码会造成createThread()一直在执行,在调用该函数的地方的后续代码都无法执行,所以这里不能使用while()
while(i--){
sleep(3);
printf("current k=%d\n",k);
}*/
}
void Child2::setI(int j)
{
i = j;
}
int Child2::getI(){
return i;
}
void Child2::setK(int j)
{
k = j;
}
int Child2::getK(){
return k;
}
}
//main.cpp
#include "b.h"
#include "c.h"
using namespace std;
using namespace xxx_label_gen;
int main()
{
Child c1;
Child2 c2;
// std::thread t1(std::bind(&Child::createThread),&c1,&c1),t2(std::bind(&Child2::createThread,&c2,&c2));
Parent *t, *t2;
t = new Child();
t->print();
t->startThread();//启动线程
cout<<"SIZEOF Parent:"<<sizeof(t)<<endl;
t2 = new Child2();
t2->print();
t2->startThread();
//下面保留一个延迟函数,确保main线程不会结束,否则前面创建的2个线程会随着main线程的结束而退出!
getchar();
cout<<"main thread exit()\n"<<endl;
}
CMakeLists.txt
cmake_minimum_required (VERSION 2.6)
project (classtest)
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X)
if(COMPILER_SUPPORTS_CXX11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -pthread")
elseif(COMPILER_SUPPORTS_CXX0X)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
else()
message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.")
endif()
set(${PROJECT_NAME}_HDRS
include/a.h
include/b.h
include/c.h
)
include_directories (include "${PROJECT_SOURCE_DIR}/include")
FILE(GLOB SRC_LIST_CPP "${PROJECT_SOURCE_DIR}/src/*.cpp")
FILE(GLOB SRC_LIST_C "${PROJECT_SOURCE_DIR}/src/*.c")
set(LINK_DIR /home/ok/code/code/classtest/lib )
set(CONSOLE_DIR /lib/x86_64-linux-gnu/)
link_directories(${LINK_DIR} ${CONSOLE_DIR})
add_executable (main test/main.cpp src/b.cpp src/c.cpp)
如果要生成class_loader能用的插件,则上面CmakeLists要增加一点内容,最终生成lib/*.so
cmake_minimum_required (VERSION 2.6)
project (classtest)
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X)
if(COMPILER_SUPPORTS_CXX11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -pthread")
elseif(COMPILER_SUPPORTS_CXX0X)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
else()
message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.")
endif()
set(${PROJECT_NAME}_HDRS
include/a.h
include/b.h
include/c.h
)
include_directories (include "${PROJECT_SOURCE_DIR}/include")
FILE(GLOB SRC_LIST_CPP "${PROJECT_SOURCE_DIR}/src/*.cpp")
FILE(GLOB SRC_LIST_C "${PROJECT_SOURCE_DIR}/src/*.c")
set(LINK_DIR /home/ok/code/code/classtest/lib )
set(CONSOLE_DIR /lib/x86_64-linux-gnu/)
link_directories(${LINK_DIR} ${CONSOLE_DIR})
add_executable (main test/main.cpp src/b.cpp src/c.cpp)
# link_directories(${LINK_DIR} ${CONSOLE_DIR})
# link_libraries(class_loader console_bridge)
target_link_libraries( main optimized
libclass_loader.so
libconsole_bridge.so
)
add_library(test SHARED ${SRC_LIST_CPP} ${${PROJECT_NAME}_HDRS})
target_link_libraries( main optimized
libclass_loader.so
libconsole_bridge.so
)