add callckbase for runnable implmentation

This commit is contained in:
侯歌 2021-08-06 13:45:25 +08:00
parent 01f9f55aa5
commit 1396387c99
14 changed files with 149 additions and 58 deletions

4
src/gui/core/callbackbase.cc Executable file
View File

@ -0,0 +1,4 @@
#include <core/callbackbase.h>
namespace cdroid{
std::atomic_int mCallbackID(0);
}

45
src/gui/core/callbackbase.h Executable file
View File

@ -0,0 +1,45 @@
#pragma once
#include <functional>
#include <type_traits>
#include <atomic>
namespace cdroid{
extern std::atomic_int mCallbackID;
template<typename R,typename... Args>
class CallbackBase{
private:
using Functor=std::function<R(Args...)>;
Functor fun;
long mID;
public:
CallbackBase(){fun=nullptr_t();mID=mCallbackID++;}
CallbackBase(const Functor&a):CallbackBase(){
fun=a;
}
CallbackBase&operator=(const Functor&a){
fun=a;
return *this;
}
CallbackBase&operator=(const CallbackBase&b){
mID=b.mID;
fun=b.fun;
return *this;
}
bool operator==(const CallbackBase&b)const{
return mID==b.mID;
}
operator bool()const{ return fun!=nullptr; }
operator int() const{ return mID; }
bool operator==(nullptr_t)const{
return fun==nullptr;
}
bool operator!=(nullptr_t)const{
return fun!=nullptr;
}
R operator()(Args...args)const{
return fun(std::forward<Args>(args)...);
}
};
}

View File

@ -85,7 +85,7 @@ namespace cdroid{
CallbackRecord* predecessor = nullptr;
for (CallbackRecord* callback = mHead; callback != nullptr;) {
CallbackRecord* next = callback->next;
if ((/*action == nullptr ||*/ callback->action.ID == action.ID)
if ((/*action == nullptr ||*/ callback->action == action)
&& (token == 0 || callback->token == token)) {
if (predecessor != nullptr) {
predecessor->next = next;

View File

@ -5,43 +5,12 @@
#include <functional>
#include <cairomm/refptr.h>
#include <cairomm/surface.h>
#include <core/callbackbase.h>
using namespace Cairo;
namespace cdroid{
class Runnable{
public:
int ID;
std::function<void()>run;
Runnable(){
run=nullptr;
}
Runnable(const Runnable&b){
run=b.run;
ID=b.ID;
}
Runnable(const std::function<void()>&f){
run=f;
}
void operator=(const std::function<void()>&f){
run=f;
}
void operator=(nullptr_t){
run=nullptr;
}
bool operator==(nullptr_t)const{
return run==nullptr;
}
bool operator!=(nullptr_t)const{
return run!=nullptr;
}
explicit operator bool()const{
return run!=nullptr;
}
void operator()(){
run();
}
};
typedef CallbackBase<void> Runnable;
class Drawable;
class ColorStateList;
class Context{

View File

@ -10,7 +10,6 @@ namespace cdroid{
UIEventSource::UIEventSource(View*v){
mAttachedView=v;
mID=0;
}
UIEventSource::~UIEventSource(){
@ -28,18 +27,23 @@ int UIEventSource::handleEvents(){
}
if(GraphDevice::getInstance().needCompose())
GraphDevice::getInstance().ComposeSurfaces();
for(auto it=mRunnables.begin();it!=mRunnables.end();it++){
LOGV_IF(it->removed,"remove %d",(int)it->run);
if(it->removed)it=mRunnables.erase(it);
}
if(hasDelayedRunners()){
RUNNER runner=mRunnables.front();
runner.run();
runner.run();//maybe user will removed runnable itself in its runnable'proc,so we use removed flag to flag it
LOGV("remove %d",(int)runner.run);
mRunnables.pop_front();
}
return 0;
}
void UIEventSource::post(Runnable& run,DWORD delayedtime){
void UIEventSource::post(const Runnable& run,uint32_t delayedtime){
RUNNER runner;
runner.removed=false;
runner.time=SystemClock::uptimeMillis()+delayedtime;
run.ID=mID++;
runner.run=run;
for(auto itr=mRunnables.begin();itr!=mRunnables.end();itr++){
if(runner.time<itr->time){
@ -58,9 +62,9 @@ bool UIEventSource::hasDelayedRunners()const{
}
void UIEventSource::removeCallbacks(const Runnable& what){
mRunnables.remove_if([&](const RUNNER& m)->bool{
return (m.run.ID==what.ID);
});
for(auto it=mRunnables.begin();it!=mRunnables.end();it++){
if(it->run==what) it->removed=true;
}
}
}//end namespace

View File

@ -8,10 +8,10 @@ namespace cdroid{
class UIEventSource:public EventHandler{
private:
int mID;
typedef struct{
nsecs_t time;
Runnable run;
nsecs_t time;
bool removed;
Runnable run;
}RUNNER;
std::list<RUNNER>mRunnables;
View*mAttachedView;
@ -22,7 +22,7 @@ public:
bool processEvents();
int checkEvents()override;
int handleEvents()override;
void post(Runnable& run,DWORD delay=0);
void post(const Runnable& run,uint32_t delay=0);
void removeCallbacks(const Runnable& what);
};

View File

@ -387,7 +387,7 @@ void AdapterView::selectionChanged(){
// by posting. This ensures that the view tree is
// in a consistent state and is able to accommodate
// new layout or invalidate requests.
if (mSelectionNotifier == nullptr) {
if (mSelectionNotifier==nullptr) {
mSelectionNotifier =[this](){
mPendingSelectionNotifier = nullptr;
if (mDataChanged /*&& getViewRootImpl() && getViewRootImpl().isLayoutRequested()*/) {

View File

@ -3422,18 +3422,19 @@ bool View::onTouchEvent(MotionEvent& mt){
return false;
}
void View::postOnAnimation(Runnable action){
void View::postOnAnimation(const Runnable& action){
postDelayed(action,10);
}
void View::postOnAnimationDelayed(Runnable action, long delayMillis){
void View::postOnAnimationDelayed(const Runnable& action, uint32_t delayMillis){
postDelayed(action,delayMillis);
}
void View::post(Runnable& what){
void View::post(const Runnable& what){
postDelayed(what,0);
}
void View::postDelayed(Runnable& what,uint32_t delay){
void View::postDelayed(const Runnable& what,uint32_t delay){
View*root=getRootView();
if(root&&(root!=this))root->postDelayed(what,delay);
}

View File

@ -354,8 +354,8 @@ protected:
bool awakenScrollBars();
bool awakenScrollBars(int startDelay, bool invalidate);
void postOnAnimation(Runnable action);
void postOnAnimationDelayed(Runnable action, long delayMillis);
void postOnAnimation(const Runnable& action);
void postOnAnimationDelayed(const Runnable& action, uint32_t delayMillis);
virtual void onSizeChanged(int w,int h,int oldw,int oldh);
virtual void onScrollChanged(int l, int t, int oldl, int oldt);
virtual void onLayout(bool ,int,int,int,int);
@ -679,10 +679,10 @@ public:
virtual bool onGenericMotionEvent(MotionEvent& event);
virtual void onHoverChanged(bool hovered);
void post(Runnable& what);
void post(const Runnable& what);
void post(const std::function<void()>&what);
void postDelayed(const std::function<void()>&what,uint32_t delay=0);
virtual void postDelayed(Runnable& what,uint32_t delay=0);
virtual void postDelayed(const Runnable& what,uint32_t delay=0);
virtual void removeCallbacks(const Runnable& what);
virtual int getBaseline();

View File

@ -283,7 +283,7 @@ bool Window::onKeyDown(int keyCode,KeyEvent& evt){
}
void Window::postDelayed(Runnable& what,uint32_t delay){
void Window::postDelayed(const Runnable& what,uint32_t delay){
if(source)source->post(what,delay);
}

View File

@ -71,7 +71,7 @@ public:
sendMessage(this,msgid,wParam,lParam,delayedtime);
}
virtual void sendMessage(View*v,DWORD msgid,DWORD wParam,ULONG lParam,DWORD delayedtime=0)override;*/
void postDelayed(Runnable& what,uint32_t delay)override;
void postDelayed(const Runnable& what,uint32_t delay)override;
void removeCallbacks(const Runnable& what)override;
void requestLayout()override;
static void broadcast(DWORD msgid,DWORD wParam,ULONG lParam);

3
tests/gui/CMakeLists.txt Normal file → Executable file
View File

@ -1,8 +1,9 @@
project(gui_test C CXX)
set(CMAKE_CXX_STANDARD 11)
aux_source_directory(./ SRCS_GUI_TESTS)
include_directories(
./
${DEPS_DIR}/include
${DEPS_DIR}/include/gui
${DEPS_DIR}/include/porting

38
tests/gui/callback.h Executable file
View File

@ -0,0 +1,38 @@
#pragma once
#include <functional>
#include <type_traits>
#include <atomic>
namespace test{
static std::atomic_int ID(0);
template<typename R,typename... Args>
class CallbackBase{
private:
using Functor=std::function<R(Args...)>;
Functor fun;
long mID;
public:
CallbackBase(){fun=nullptr_t();mID=ID++;}
CallbackBase(const Functor&a):CallbackBase(){
fun=a;
}
CallbackBase&operator=(const Functor&a){
fun=a;
return *this;
}
CallbackBase&operator=(const CallbackBase&b){
mID=b.mID;
fun=b.fun;
return *this;
}
bool operator==(const CallbackBase&b){
return mID==b.mID;
}
operator bool()const{
return fun!=nullptr;
}
R operator()(Args...args)const{
return fun(std::forward<Args>(args)...);
}
};
}

29
tests/gui/callback_tests.cc Executable file
View File

@ -0,0 +1,29 @@
#include <gtest/gtest.h>
#include <windows.h>
#include <ngl_os.h>
#include <sys/time.h>
#include <core/systemclock.h>
#include <cdlog.h>
#include <functional>
#include <callback.h>
class CALLBACK:public testing::Test{
public :
virtual void SetUp(){
}
virtual void TearDown(){
}
};
TEST_F(CALLBACK,loop){
test::CallbackBase<void> c0([](){});
test::CallbackBase<void,int> c1([](int a){printf("a=%d\r\n",a);});
test::CallbackBase<void,int,int>cb2([](int a,int b){printf("a=%d,b=%d\r\n",a,b);});
test::CallbackBase<int,int,int>cbr2([](int a,int b){return a+b;});
c1(123);
cb2(123,456);
printf("cbr2=%d\r\n",cbr2(234,345));
cbr2=[](int a,int b){return a*b;};
printf("cbr2=%d\r\n",cbr2(234,345));
}