线程 Joining and Detaching相关函数4个
pthread_joinpthread_detach
pthread_attr_setdetachstate
pthread_attr_getdetachstate
Joining的作用
Joining是线程同步的方法之一
当且仅当线程被设置为joinable时其可被Joining
一个例子:
#include <pthread/pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define NUM_THREADS 4
void *BusyWork(void *t)
{
int i;
long tid;
double result=0.0;
tid = (long)t;
printf("Thread %ld starting\n",tid);
for (i=0; i<1000000; i++)
{
result = result + sin(i) * tan(i);
}
printf("Thread %ld done. Result = %e\n",tid, result);
pthread_exit((void*) t);
}
int main (int argc, char *argv[])
{
pthread_t thread[NUM_THREADS];
pthread_attr_t attr;
int rc;
long t;
void *status;
//! 设置线程属性
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
for(t=0; t<NUM_THREADS; t++)
{
printf("Main: creating thread %ld\n", t);
rc = pthread_create(&thread[t], &attr, BusyWork, (void *)t);
if (rc)
{
printf("ERROR; return code from pthread_create()is %d\n", rc);
exit(-1);
}
}
//! 销毁线程属性
pthread_attr_destroy(&attr);
for(t=0; t<NUM_THREADS; t++)
{
rc = pthread_join(thread[t], &status);
if (rc)
{
printf("ERROR; return code from pthread_join()is %d\n", rc);
exit(-1);
}
printf("Main: completed join with thread %ld having a status of %ld\n",t,(long)status);
}
printf("Main: program completed. Exiting.\n");
pthread_exit(NULL);
}
1.使用pthread的理由
2个字:简单
2.pthread组件
thread,
mutex,
condition var
synchronization
3.线程的终止和产生
小例:
#include <pthread/pthread.h>
#include <stdio.h>
#define NUM_THREADS 5
void *PrintHello(void *threadid)
{
long tid;
tid = (long)threadid;
printf("Hello World! It's me, thread #%ld!\n", tid);
pthread_exit(NULL);
}
int main (int argc, char *argv[])
{
pthread_t threads[NUM_THREADS];
int rc;
long t;
for(t=0; t<NUM_THREADS; t++)
{
printf("In main: creating thread %ld\n", t);
rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t);
if (rc)
{
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
pthread_exit(NULL);
return 0;
}
通过pthread_create来创建线程
其第一个参数为线程id,第二个为线程属性,第三个为线程函数,最后一个为数据参数
那么线程如何终止呢:
1.从运行函数终止
2.调用pthread_exit终止
3.调用pthread_cance
4.进程终止
向线程传递参数
#include <pthread/pthread.h>
#include <stdio.h>
#include <string>
#include <iostream>
#define NUM_THREADS 5
struct Data
{
std::string name;
};
Data* data_impl;
void *PrintHello(void* data_ptr)
{
struct Data* data;
data = (Data*)data_ptr;
std::cout<<data->name<<std::endl;
pthread_exit(NULL);
}
int main (int argc, char *argv[])
{
pthread_t threads[NUM_THREADS];
data_impl = new Data[NUM_THREADS];
data_impl[0].name = "T1";
data_impl[1] .name= "T2";
data_impl[2] .name= "T3";
data_impl[3] .name= "T4";
data_impl[4] .name= "T5";
for(int t=0; t<NUM_THREADS; t++)
{
int rc = pthread_create(&threads[t], NULL, PrintHello,&data_impl[t]);
}
pthread_exit(NULL);
delete []data_impl;
return 0;
}
其他相关线程库:
1.zthread,
2.opentherad
3.boost therad
4.原生态的平台线程函数
boost是一个很好的库
但是并不是完美的
在使用的时候需要详细注意
std::string tag;
boost::tokenizer<> tok(std::string("猫 狗 猪"));
for(boost::tokenizer<>::iterator beg=tok.begin();beg!=tok.end();++beg)
{
tag += *beg;
tag += "+";
}
std::cout<<tag<<std::endl;
大家说说结果吧
1.原DLL分为2个gcore和device(这样可以在其他软件中使用前者)
2.支持xp,vista,win7,linux操作系统
3.支持msvc7.1,8.0,9.0,mingw,bcb,dev++,codeblock编译器系列
4.提供方便易用的xml序列化框架一个
5.提供可插式图形插件接口
6.移除原有的RefPtr对象改用boost系列智能指针
7.移除原有的Manager对象
8.修改了filesystem接口
9.在UI中增加了栅格主题,UI工厂,UI_ProgressBar增加了进度的显示
10.粒子系统中增加了粒子工厂
11.移除了原有的Cursor类
12.移除线程类对象(改用boost thread.)
13.增加了Helper文件以方便用户
14.增加了Sprite2对象
盖莫引擎2.3.0算是做完了
不过这个做的很不尽人意(不过没关系咱慢慢做只要坚持O(∩_∩)O~)
一个问题就是引擎中的RefPtr设计有点问题
索性下个引擎版本就是用boost库吧
免得一些基础需要自己写
要使用boost库其中的智能指针必不可少
林林总总有好几个类型
不过常用得还是3个
scoped_ptr,
shared_ptr,
weak_ptr
这里先说shared_ptr
它还是引用计数类型的指针咯
貌似比较好用(但是根本还是在于使用的人)
为了正确使用它需要注意几个问题
1.多线程环境和循环引用
应该配合weak_ptr
2.使用了shared_ptr就不应该使用其他内存管理机制
3.不要构造临时的shared_tr作为函数参数
4.其他...
摘要: Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->【基本介绍】盖莫音频引擎SDK1.6.0(类似fmod音频api)原本为盖莫游戏引擎开发当前支持win7,xmp,vista操作系统支持10种音频格式:mp3,ogg,wav,au,aiff,mod,it...
阅读全文
接上篇
我们接着说UI部分的控件基类
控件基类应该具备的要素
1.按名生成
2.控件尺寸
3.控件大小
4.控件状态
5.对消息事件的处理
6.控件渲染
7.控件检测
8.控件文本
然后具体代码如下:
///////////////////////////////////////////////////////////
/// 定义UI控件基类
///////////////////////////////////////////////////////////
class GAPI UI_Widget : public SlotHolder,public UI_EventHandler,public Object
{
public:
typedef std::list<UI_EventListener*> UIEventListener;
typedef std::list<UI_EventListener*>::iterator UIEventListenerItr;
public:
////////////////////////////////////////////////////////
/// 窗体构造和析构
////////////////////////////////////////////////////////
explicit UI_Widget(UI_Widget* parent = NULL,const engine_wstring& text = L"widget");
virtual ~UI_Widget();
public:
////////////////////////////////////////////////////////
/// 获取,设置设置窗体文本
////////////////////////////////////////////////////////
engine_wstring GetText()const{return text_;}
void SetText(const engine_wstring& text);
public:
////////////////////////////////////////////////////////
/// 窗体大小和尺寸
////////////////////////////////////////////////////////
Size GetSize()const;
void SetSize(const Size& size);
Point GetPosition()const;
void SetPosition(const Point& point);
////////////////////////////////////////////////////////
/// 获取窗体推荐大小
////////////////////////////////////////////////////////
virtual Size GetRecommendedSize()const;
public:
////////////////////////////////////////////////////////
/// 检测给定点下控件
////////////////////////////////////////////////////////
UI_Widget* GetWidgetBelow(int x,int y);
////////////////////////////////////////////////////////
/// 获取本控件的顶层控件
////////////////////////////////////////////////////////
UI_Widget* GetTopWidget()const;
////////////////////////////////////////////////////////
/// 获取,设置父窗体
////////////////////////////////////////////////////////
UI_Widget* GetParentWidget()const;
void SetParentWidget(UI_Widget* parent);
public:
////////////////////////////////////////////////////////
/// 设置,获取控件边框
////////////////////////////////////////////////////////
void SetBorder(const RefPtr<UI_AbstractBorder>& border);
RefPtr<UI_AbstractBorder> GetBorder()const;
////////////////////////////////////////////////////////
/// 设置,获取是否渲染边框
////////////////////////////////////////////////////////
void SetBorderVisible(bool visible);
bool IsBorderVisible();
public:
////////////////////////////////////////////////////////
/// 增加,移除事件消息
////////////////////////////////////////////////////////
void AddEventListener(UI_EventListener* listener);
void RemoveEventListener(UI_EventListener* listener);
////////////////////////////////////////////////////////
/// 消息处理
////////////////////////////////////////////////////////
virtual bool Process(const UI_Event& event);
public:
////////////////////////////////////////////////////////
/// 焦点函数
////////////////////////////////////////////////////////
bool IsFocusOn()const;
void SetFocusOn(bool focus);
void ChangedFocusOn();
////////////////////////////////////////////////////////
/// 设置,检测是否为活动控件
////////////////////////////////////////////////////////
void SetAsActiveWidget();
bool IsActiveWidget()const;
////////////////////////////////////////////////////////
/// 检测控件层次关系
////////////////////////////////////////////////////////
virtual bool DoesHierarchyContain(UI_Widget* widget)const;
public:
////////////////////////////////////////////////////////
/// 显示,隐藏窗体
////////////////////////////////////////////////////////
void SetVisible(bool visible);
void Show();
void Hide();
bool IsVisible()const;
////////////////////////////////////////////////////////
/// 窗体状态函数
////////////////////////////////////////////////////////
void IsEnable(){enabled_ = true;}
void Disable(){enabled_ = false;}
bool IsEnabled()const{return enabled_;}
public:
////////////////////////////////////////////////////////
/// 窗体渲染
////////////////////////////////////////////////////////
void Render();
////////////////////////////////////////////////////////
/// 当窗体关闭的时候发射信号
////////////////////////////////////////////////////////
Signal0 closed_;
////////////////////////////////////////////////////////
/// 窗体数据载入
////////////////////////////////////////////////////////
virtual bool Load(const engine_string& file,const engine_string& widget);
protected:
////////////////////////////////////////////////////////
/// 执行函数
////////////////////////////////////////////////////////
virtual void OnResize(){}
virtual void OnMove(){}
virtual void OnTextChanged(){}
virtual void OnShow(){}
virtual void OnHide(){}
virtual void OnGainedFocus(){}
virtual void OnLostFocus(){}
virtual void OnDraw(){}
private:
UI_Widget* parent_;
UIEventListener message_listeners_;
engine_wstring text_;
Size size_;
Point position_;
bool visible_;
bool enabled_;
RefPtr<UI_AbstractBorder> border_;
bool border_visible_;
private:
DECLARE_OBJECT(UI_Widget)
};
}
#ifdef G_COMPILER_MSVC
#pragma warning(pop)
#endif
需要说明的就是这里有3个父类
一个是Object
一个是SlotHolder这是消息桩
另外一个是UI_EventHandler负责对事件的处理
需要说明的是UI_Widget总是和UI_WidgetManager配合使用的
毕竟UI上下文最大只能有一个活动控件
接上文:http://www.cppblog.com/gaimor/archive/2010/09/30/128134.html
本文我们接着说UI库的消息事件部分:
1.UI基本事件类型
基本上就下面几种:
////////////////////////////////////////////////////////////
/// 枚举UI消息类型
////////////////////////////////////////////////////////////
enum UI_EVENT
{
//! 鼠标移动
UI_EVENT_MOUSE_MOVE = 0,
//! 鼠标点击
UI_EVENT_MOUSE_CLICK,
//! 鼠标进入
UI_EVENT_MOUSE_ENTERED,
//! 鼠标退出
UI_EVENT_MOUSE_EXITED,
//! 鼠标滚轮事件
UI_EVENT_MOUSE_WHEEL,
//! 字符输入
UI_EVENT_CHAR_INPUT,
//! 键盘按键
UI_EVENT_KEY_PRESS,
//! 按键退出
UI_EVENT_KEY_RELEASE,
//! 焦点事件
UI_EVENT_LOST_FOCUSE,
UI_EVENT_GAIN_FOCUSE,
//! 滑块事件
UI_EVENT_SLIDER_MOVE,
//! 编辑事件
UI_EVENT_EDIT,
//! 选择,反选择
UI_EVENT_SELECTED,
UI_EVENT_DESELECTED
};
2.
关于事件一般就3个相关对象:
事件,消息听者和消息处理对象3个单元块:
如下所示:
///////////////////////////////////////////////////////////
/// 定义引擎事件基类模板
///////////////////////////////////////////////////////////
template<class EventType = int>
class Event : NonCopyable
{
public:
///////////////////////////////////////////////////////
/// 事件基类构造函数
///////////////////////////////////////////////////////
Event(const EventType& type):type_(type){}
////////////////////////////////////////////////////////
/// 事件基类析构函数
////////////////////////////////////////////////////////
virtual ~Event(){}
////////////////////////////////////////////////////////
/// 获取事件类型
////////////////////////////////////////////////////////
EventType GetEventType()const{return type_;}
private:
////////////////////////////////////////////////////////
/// 数据成员变量
////////////////////////////////////////////////////////
EventType type_;
};
////////////////////////////////////////////////////////////
/// 定义事件听者基类
////////////////////////////////////////////////////////////
template<class Event,class Target>
class EventListener
{
public:
////////////////////////////////////////////////////////
/// 事件听者虚析构函数
////////////////////////////////////////////////////////
virtual ~EventListener(){}
////////////////////////////////////////////////////////
/// 消息派送
////////////////////////////////////////////////////////
virtual bool Dispatch(const Event& message,Target object) = 0;
};
////////////////////////////////////////////////////////////
/// 定义事件处理者基类
////////////////////////////////////////////////////////////
template<class Event,class EventListener>
class EventHandler
{
public:
////////////////////////////////////////////////////////
/// 事件听者虚析构函数
////////////////////////////////////////////////////////
virtual ~EventHandler(){}
////////////////////////////////////////////////////////
/// 消息处理
////////////////////////////////////////////////////////
virtual bool Process(const Event& message){return false;}
////////////////////////////////////////////////////////
/// 增加,移除事件消息
////////////////////////////////////////////////////////
virtual void AddEventListener(EventListener* listener){}
virtual void RemoveEventListener(EventListener* listener){}
};
然后便是模板实例:
typedef Event<UI_EVENT> UI_Event;
typedef EventListener<UI_Event,UI_Widget*> UI_EventListener;
typedef EventHandler<UI_Event,UI_EventListener*> UI_EventHandler;
说实话可以不这样做而是用boost::function之类的函数绑定
但是没法子这样写我习惯了 呵呵
2.下面是UI事件的承接部分:
通过UI管理器承接输入输出系统的消息响应:
{
////////////////////////////////////////////////////////////
/// 盖莫GUI管理器
////////////////////////////////////////////////////////////
class GAPI UI_WidgetManager : public UI_EventListenerImpl
public:
////////////////////////////////////////////////////////
/// 按键处理
////////////////////////////////////////////////////////
bool OnMouseLeftDown(int x,int y);
bool OnMouseLeftUp(int x,int y);
bool OnMouseMiddleDown(int x,int y);
bool OnMouseMiddleUp(int x,int y);
bool OnMouseRightDown(int x,int y);
bool OnMouseRightUp(int x,int y);
bool OnMouseMove(int x,int y);
bool OnChar(wchar_t code);
bool OnKeyDown(int code);
bool OnKeyUp(int code);
bool OnMouseWheel(int z);
public:
3.事件生成:
以上2部分分别是UI事件对象系列和UI事件输入部分
下面设计UI事件的生成
无论是鼠标还是键盘事件实际上都相当于生成了一个新的事件
举例如下:
OnMouseLeftDown(int x,int y)
如果该函数被调用
那么就说明鼠标的左键被点击同时我们还知道了点击的位置坐标
这样就生成了一个UI_MouseClickEvent
对象
不过这里需要考虑是鼠标双击还是单击
这就要考虑本次点击和上次点击的时间间隔了
这样就生成了一个UI鼠标事件
那本事件应该传给谁?
应该是目标对象
直观一点应该是传给鼠标当前位置下的控件对象
但是考虑到实际情况
这里有一个聚焦控件和活动控件的概念
比如说我们打开一个对话框(这是一个聚焦控件)
对话框上有1个按键
当用户点击本按键则消息发送给这个按键了
但是当鼠标移出对话框之外
一般情况其他控件此时处于非活动状态
消息应该发送给聚焦控件
所以这里至少有3各类型的控件指针分别为:聚焦控件,活动控件以及鼠标下控件(当然他们可以是同一控件)
在这里需要说明这三个控件是这样切换的
如果发生特定的uI事件则修改当前的聚焦控件等对象了
4.具体控件对消息的处理:
生成特定消息,并发送给相应的控件对象之后那么控件就需要相应该消息了:
控件对象的相关函数:
///////////////////////////////////////////////////////////
/// 定义UI控件基类
///////////////////////////////////////////////////////////
class GAPI UI_Widget : public SlotHolder,public UI_EventHandler,public Object
{
public:
typedef std::list<UI_EventListener*> UIEventListener;
typedef std::list<UI_EventListener*>::iterator UIEventListenerItr;
void RemoveEventListener(UI_EventListener* listener);
////////////////////////////////////////////////////////
/// 消息处理
////////////////////////////////////////////////////////
virtual bool Process(const UI_Event& event)
在这里我们通过Process函数来接受UI管理器传过来的消息对象.
这里是想要的处理
注意我们并不直接根据消息响应控件的各种状态!
而是通过迭代消息听者链表的
如下:
bool UI_Widget::Process(const UI_Event& event)
{
bool ret = false;
if(IsVisible() && IsEnabled())
{
UIEventListenerItr it;
for(it = message_listeners_.begin();it != message_listeners_.end();++it)
{
UI_EventListener* listener = *it;
ret = ret || listener->Dispatch(event,this);
}
//! 处理控件边框事件
if(border_)
border_->Process(event);
}
return ret;
}
当消息传来之后我们并不能确定这就是本控件所需要的消息需要验证它
如何验证?
就看当前控件是不是可显示和活动的咯
同时如何控件有边框对象我们则把消息发给它以改变可能的边框外观
下篇:UI设计概要4:UI控件对象
接上文:http://www.cppblog.com/gaimor/archive/2010/09/27/127900.html
第一篇是关于UI布局管理器的文章
本文主要说说引擎UI部分组件的问题
在这里UI组件是指UI中的各个基础模块而非UI控件也
在本引擎之中当前UI组件有以下几个基础单元
1.UI_Widget UI控件的基类
2.UI_AbstractBorder UI控件边框类
3.UI_AbstractLayouter UI布局管理器类
4.UI_Event/UI_EventHandler,UI_EventListerner UI事件处理家族
5.UI_Brush UI库画笔(当前基于OpenGL)
6.UI_AbstractTheme UI库控件主题
7.UI_ProptyScheme UI库主题对象
8.UI_WidgetManager UI库管理器
9.UI_Factory UI库工厂对象
10.其他通用对象
以上所有对象构成了UI库的框架
下面说下各个部分的功能
1.UI_Widget UI基本控件 所有控件的基类
2.UI_AbstractBorder 控件控件对象边框外观
3.UI_AbstractTheme 控件主题
以上3着构成所见控件外观
每一个控件都有一个主题和边框对象
所有同质控件都采用统一的控件主题以保证统一的外观
当前UI_Border设计了2中 一种为线性边框一种为状态边框
当前主题设计了3中分别为简单主题,位图主题和矩形主题
UI布局管理器上文已经说过当前不再赘述
UI事件处理这块内容比较多 下文说吧
UI画笔的作用是绘制对象元素比如绘制线条,矩阵设置颜色等等很简单的咯
UI_PertptyShceme是一个控件主题的集合包含了所有控件类型的主题
在渲染控件的时候调用对等的主题绘制控件
控件管理器是UI库的中枢
负责统一渲染队列控件和调度输入输出事件
关于UI工厂则负责按名生成控件指针咯
我一直力图把UI库的实际简单化
但是总是做不到
而且越做越复杂的
注意当前并没有涉及脚本,
UI编辑器以及完成所有控件对象的开发
关于脚本我想采用得到脚本有lua,anglescrip或者自定义脚本
关于编辑器我想采用wxwidget or qt
虽然很慢但是我一直在努力 呵呵
下篇:UI设计概要3:UI消息
一直想把引擎的UI部分做强做大可是发现这个难度还是不小
所以只能一步一步蚕食之
一步一步来吧
先说下控件布局管理器吧
布局管理器的目的是按照一定规则排列控件于给定范围内
这是其基本目的
很显然基本的布局管理对象应该包含以下2个基本功能
1.控件的加入和删除
2.应用布局管理器
当然也可以有其他附加功能
比如获取控件个数等等
所以我把抽象控件布局对象设计如下:
///////////////////////////////////////////////////////////
/// 定义引擎UI布局管理器
///////////////////////////////////////////////////////////
class GAPI UI_AbstractLayouter : public Object
{
public:
typedef std::list<UI_Widget*> Widgets;
public:
UI_AbstractLayouter();
virtual ~UI_AbstractLayouter();
public:
////////////////////////////////////////////////////////////
/// 布局管理器加载控件
////////////////////////////////////////////////////////////
void AddWidget(UI_Widget* widget);
////////////////////////////////////////////////////////////
/// 布局管理器移除控件
////////////////////////////////////////////////////////////
void RemoveWidget(UI_Widget* widget);
////////////////////////////////////////////////////////////
/// 布局管理器移除所有子控件
////////////////////////////////////////////////////////////
void RemoveAllWidget();
////////////////////////////////////////////////////////////
/// 布局管理器控件排列
////////////////////////////////////////////////////////////
virtual void ApplyLayouter(UI_Widget* parent) = 0;
protected:
Widgets widgets_;
private:
DECLARE_OBJECT(UI_AbstractLayouter)
};
然后就是具体的几种布局管理器对象了
下面是我当前弄的4种布局管理器了
分别为:
UI_FlowLayouter
流式布局管理的布局策略是从左到右依次设定控件位置如果超出父控件则按照设定的竖直布局换行重新布局(注意它并不改变控件的大小)
UI_GridLayouter
格子布局管理的策略则是工具设定布局间隔和子控件,父亲控件个数重写设置所有的子控件大小(这样所有的子控件大小就一样了)然后把所有的子控件放置在一个一个的格子中
UI_VLayouter
UI_VLayouter和UI_HLayouter则是我从QT中借鉴来的
IU_VLayouter把所有子控件按照从上到下的方式依次布局(不改变子控件大小)(可能会超出父控件喔)
UI_HLayouter
这个就不说了
当然还可以定制其他布局管理器了
比如UI_DockLayouter
UI_CenterLayouter等等基本原理都是一样的
做了游戏引擎这么久说实话
UI真是一个大块头
对于UI我的设计理念就是使用简单,功能丰富
题外话1:08年11月的时候我就想设计一套UI库
之前认为游戏UI是使用windows API话的 呵呵
题外话2:网上关于使用一些UI库的例子很多但是关于设计UI库的例子似乎不多
题外话3:说实话我觉得写博客是交流思想共同探讨而非其他