Project1

标题: [还是让这个帖子在水区吧][Ruby]召唤……求Dump [打印本页]

作者: yangff    时间: 2011-4-24 10:50
标题: [还是让这个帖子在水区吧][Ruby]召唤……求Dump
本帖最后由 yangff 于 2011-4-26 00:16 编辑
  1. module Game
  2.   module Safe
  3.     module_function
  4.     def safe(level,join=false,mid=nil,eid=nil)
  5.       result = nil
  6.       #Game.temp.events[mid][eid]
  7.       
  8.       k = Thread.start {
  9.         $SAFE = level
  10.         result = yield
  11.         Game.temp.events[mid][eid]=nil if mid!=nil and eid!=nil
  12.       }
  13.       if mid!=nil and eid!=nil
  14.         Game.temp.events[mid]={} if Game.temp.events[mid].nil?
  15.         Game.temp.events[mid][eid] = k
  16.       end
  17.       k.join if join
  18.         
  19.       #p "exit:"
  20.       result
  21.     end
  22.   end
  23. end
  24. #alias new_eval eval
  25. #def eval(*args)
  26.   
  27. # Game::Safe.safe(3) { new_eval(args)}
  28. #end
  29. #事件响应方法
  30. def startevent(mapid,eventid,join)
  31.   Game::Safe.safe(3,join,mapid,eventid) { yield }
  32. end
  33. def continue_event(mapid)
  34.   for i in Game.temp.events[mapid]
  35.     i.run
  36.   end
  37. end
  38. def change_map_of_ev(mapid)
  39.   for i in Game.temp.events[mapid]
  40.     i.stop
  41.   end
  42. end
  43. module Events
  44.   def self.run(event,mapid,eventid,join=true) #event=Proc.new {
  45.     startevent(mapid,eventid,join) { event.call }
  46.   end
  47. end
复制代码
这样写,如果在event里面写
Game.scene="Battle"
change_map_of_ev(Game.temp.map_id)
show_Message(...)
1、会不会刮起线程
2、战斗结束后恢复后执行continue_event(Game.temp.map_id)会不会继续执行show_Message(...)还是会傻乎乎的重头开始执行?
3、Game会受到污染吗?
0----------------------------------------------------------------------------------------------------0
Thread怎么Dump
如果不能Dump怎么在下次运行的时候恢复到上次运行时的位置?
0----------------------------------------------------------------------------------------------------0
还有同样的dump问题,Proc怎么dump
作者: 苏小脉    时间: 2011-4-24 13:31
1、会不会刮起线程

根据有限的上下文,for i in Game.temp.events[mapid] 这里的 i 枚举的是 Thread,但 Thread 默认没有 stop 这个实例方法。如果是自行定义的,那就需要具体实现才能判断。默认的库中有一个 Thread.stop 的单例方法可以挂起当前线程,除此之外没有别的直接挂起外部某线程的接口,但是可以通过在本来想挂起所有线程之前加一把互斥锁来实现同步。

战斗结束后恢复后执行continue_event(Game.temp.map_id)会不会继续执行show_Message(...)还是会傻乎乎的重头开始执行?

假设之前线程被挂起,那之后恢复了执行权后自然是继续执行。

Thread.pass、Thread.stop、Thread#run 等直接控制线程调度器的方法,在 Ruby 1.8 的绿色环境中的行为是可预知的,但是一旦涉及到 1.9 的本地线程,尤其是抢先式多任务系统下就很危险了,官方的文档说它们本身都不是线程安全的(不是原子操作),所以强烈不推荐使用。一切和同步有关的操作都应该由信号对象来控制,而 Ruby 中内置的只有互斥锁。Ruby 1.8 有 Thread.critical 这个变量来标记临界区的开始或结束,但在 1.9 中被废弃了。

Game会受到污染吗?

请定义“污染”。

Thread怎么Dump

不妨试试这个 Gem。
http://rubygems.org/gems/thread-dump/versions/0.0.1

怎么在下次运行的时候恢复到上次运行时的位置?

线程的基本行为就是这么被定义的。

Proc怎么dump

http://rubystuff.org/nodewrap/

Proc 包含了解释器内部的闭包数据,默认既然没有接口,所以只能 Hack 解释器了。
作者: yangff    时间: 2011-4-24 13:34
本帖最后由 yangff 于 2011-4-24 13:37 编辑
苏小脉 发表于 2011-4-24 13:31
根据有限的上下文,for i in Game.temp.events[mapid] 这里的 i 枚举的是 Thread,但 Thread 默认没有 sto ...


问题是我用的RM= = ,污染请看¥SAFE

Thread.stop 的单例方法可以挂起当前线程

那要在外面怎么挂起他= =
作者: 苏小脉    时间: 2011-4-24 14:01
yangff 发表于 2011-4-24 13:34
问题是我用的RM= = ,污染请看¥SAFE

Thread.stop 的单例方法可以挂起当前线程

$SAFE 的设定是局部于块的,也就是在某个 proc 里设定的 $SAFE 只会影响该 proc 内部的对象。上面那段代码就是在 Thread.new 的块中设定 $SAFE 的,所以不会影响在外部就已经建立了的 Game 对象(Game 是一个 Module 的实例),Game.temp(虽然不知道是啥?),以及 Game.temp.events(一个 Hash 对象)。Thread.new 块内部的 yield 如果返回一个新分配的对象,那就会被污染。nil 是立即值,不会重新分配,所以 Game.temp.events 的元素也不会被污染。

那要在外面怎么挂起他= =

为什么非要挂起?如果是想同步,那完全可以通过信号对象实现,抑或是在线程内部添加一个标记的判断,外部将标记设为真的时候就不继续执行。1.9 是本地线程,在 Win32 下倒是可以通过 Ruby 扩展获取线程标识,然后传递给 SuspendThread,而 1.8 是解释器内部的调度器,除了 Hack 没别的办法。
作者: yangff    时间: 2011-4-24 17:37
苏小脉 发表于 2011-4-24 14:01
$SAFE 的设定是局部于块的,也就是在某个 proc 里设定的 $SAFE 只会影响该 proc 内部的对象。上面那段代 ...

必须要挂起啊= =比如线程执行一般调用战斗,自然是要暂停这个地图里面的线程,等战斗完了再恢复……这些线程自然五花八门,有触发战斗的线程,有并行处理的,巴拉巴拉……
作者: D阿尔西斯2    时间: 2011-4-24 22:14
- -哪个混蛋转的= =咱这是VX啊fuck2拜托了……
作者: 苏小脉    时间: 2011-4-25 02:26
yangff 发表于 2011-4-24 17:37
必须要挂起啊= =比如线程执行一般调用战斗,自然是要暂停这个地图里面的线程,等战斗完了再恢复……这些 ...

我说了可以通过信号对象来实现。战斗开始后加锁,其它线程尽数被锁在外面,只有当前有钥匙的负责战斗过程的线程有权执行。
作者: yangff    时间: 2011-4-25 18:01
本帖最后由 yangff 于 2011-4-25 18:02 编辑
苏小脉 发表于 2011-4-25 02:26
我说了可以通过信号对象来实现。战斗开始后加锁,其它线程尽数被锁在外面,只有当前有钥匙的负责战斗过程 ...


[信号对象]是什么= =求门 ,不大理解
作者: IamI    时间: 2011-4-25 18:47
互斥锁,在此对象被解锁以前其他线程不能操作。
作者: yangff    时间: 2011-4-25 22:38
IamI 发表于 2011-4-25 18:47
互斥锁,在此对象被解锁以前其他线程不能操作。

可战斗和地图都在主线程,事件在子线程,要给虾米东西上锁呢?
作者: 苏小脉    时间: 2011-4-25 23:17
本帖最后由 苏小脉 于 2011-4-25 23:21 编辑
yangff 发表于 2011-4-25 22:38
可战斗和地图都在主线程,事件在子线程,要给虾米东西上锁呢?


给单个共享的锁上锁,也就是只能是 0 或者 1 的二元信号量。

  1. lock = Mutex.new
  2. # ...
  3. Thread.fork do
  4.   if !lock.locked?
  5.     # ...
  6.   end
  7. end
  8. # ...
  9. lock.lock
  10. # ...
  11. # 战斗过程
  12. # ...
  13. lock.unlock
复制代码
只有事件线程之间异步执行才需要用这种可重入的 Mutex.locked? 判断方式。

1.9 可以直接用 Thread.exclusive do ... end 执行临界区,1.8(RM)的话,在战斗开始前打开 Thread.critical 开关,结束后关闭也能实现相同的效果。
作者: yangff    时间: 2011-4-26 00:04
可是那如果我的代码不是loop而是这样的
showMessage(...)
showMessage(...)
...
showAni(...)
那岂不是要
showMessage(...)if !lock.locked?
showMessage(...) if !lock.locked?
...
showAni(...) if !lock.locked?
甚至showMesage里面也要……
作者: 苏小脉    时间: 2011-4-26 00:25
本帖最后由 苏小脉 于 2011-4-26 00:25 编辑
yangff 发表于 2011-4-26 00:04
可是那如果我的代码不是loop而是这样的
showMessage(...)
showMessage(...)


可以用 Thread.critical。

  1. Thread.critical = true
  2. # ... 临界区 ...
  3. Thread.critical = false
复制代码





欢迎光临 Project1 (https://rpg.blue/) Powered by Discuz! X3.1