2011-09-25 4 views
1

나는 Go에서 간단한 이벤트 루프 래퍼를 만들려고 노력해 왔습니다. 하지만 난 어려워졌습니다. 어떻게 현재 스레드에서 작업을 추적해야합니까? CurrentTick이 함수를 실행하기를 원했고 호출 함수가 종료 되더라도 CurrentTick에서 실행되는 모든 함수가 종료 될 때까지 다음 틱을 시작하지 마십시오. 스레드 수를 모니터하기 위해 뮤텍스를 사용할 수 있다고 생각했지만, CPU를 스로틀 링한다는 것을 계속 확인하면 깨달았습니다. 내가 시간을 사용했다면 잠잠해질 것입니다. 어떻게 문제를 해결하겠습니까?이동 중에 대기 시간이 짧은 스레드를 기다리는 방법은 무엇입니까?

package eventloop 

import (
    "reflect" 
) 

type eventLoop *struct{ 
    functions []reflect.Value 
    addFunc chan<-/*3*/ reflect.Value 
    mutex chan/*1*/ bool 
    threads int 
} 

func NewEventLoop() eventLoop { 
    var funcs chan reflect.Value 
    loop := eventLoop{ 
     []Reflect.Value{}, 
     funcs = make(chan reflect.Value, 3), 
     make(chan bool, 1), 
     0, 
    } 
    go func(){ 
     for { 
      this.mutex <- 1 
      if threads == 0 { 
      } 
     } 
    } 
} 

func (this eventLoop) NextTick(f func()) { 
    this.addFunc <- reflect.ValueOf(f) 
} 

func (this eventLoop) CurrentTick(f func()) { 
    this.mutex <- 1 
    threads += 1 
    <-this.mutex 
    go func() { 
     f() 
     this.mutex <- 1 
     threads -= 1 
     <-this.mutex 
    }() 
} 
+0

나는 이것이 내 자신을 알아 냈다고 생각하지만, 그것을 테스트 할 것이고, 그것이 아픈 경우에는 대답으로 먼저 확인해 볼 것입니다. –

답변

2

내가 당신의 의도를 이해한다면, 나는 당신이 지나치게 복잡해지고 있다고 생각합니다. 나는 이런 식으로 할 거라고 :

package eventloop 

type EventLoop struct { 
    nextFunc chan func() 
    curFunc chan func() 
} 

func NewEventLoop() *EventLoop { 
    el := &EventLoop{ 
     // Adjust the capacities to taste 
     make(chan func(), 3), 
     make(chan func(), 3), 
    } 
    go eventLoop(el) 
    return el 
} 

func (el *EventLoop) NextTick(f func()) { 
    el.nextFunc <- f 
} 

func (el *EventLoop) CurrentTick(f func()) { 
    el.curFunc <- f 
} 

func (el *EventLoop) Quit() { 
    close(el.nextFunc) 
} 

func eventLoop(el *EventLoop) { 
    for { 
     f, ok := <-el.nextFunc 
     if !ok { 
      return 
     } 
     f() 

     drain: for { 
      select { 
      case f := <-el.curFunc: 
       f() 
      default: 
       break drain 
      } 
     } 
    } 
} 

가 사용하기에 따라, 당신은 당신의 프로그램이 종료하기 전에 루프 끝에서 모든 작업이 있는지 확인하기 위해 몇 가지 동기화를 추가해야 할 수 있습니다.

+0

"CurrentTick"동기화를 허용하지 않는 경우에만 작동합니다. 나는 그것을 조금 더 복잡하게하려고 노력하고있다. –

+2

설명해 주시겠습니까? 내 코드에서는 채널 보내기가 CurrentTick을 대체합니다. 내가 말할 수있는 한, 내 코드는 사용자의 것과 동일한 방식으로 함수를 실행하지만 기계는 적습니다. NextTick이 부분적으로 누락 된 것처럼 보이기 때문에 코드에서 수행해야하는 작업을 이해할 수 없다는 것을 인정합니다. –

+1

네, 답을 바탕으로 코드를 수정했습니다. 이게 당신이 원하는 것에 더 가깝습니까? –

1

용량 대신 길이 15를 사용하는 등 많은 문제와 임의의 문제가 발생한 후에 직접 계산했습니다 ... 카운터를 감소시킨 후에 스레드에서 메시지를 보내는 것처럼 보입니다. (loop.tick 부분은 인라인 될 수 있지만 걱정하지 않습니다.)

package eventloop 

type eventLoop struct{ 
    functions []func() 
    addFunc chan/*3*/ func() 
    mutex chan/*1*/ bool 
    threads int 
    waitChannel chan bool 
    pauseState chan bool 
} 
func (this *eventLoop) NextTick (f func()) { 
    this.addFunc <- f 
} 

func (this *eventLoop) tick() { 
    this.mutex <- true 
    for this.threads != 0 { 
     <-this.mutex 
     <-this.waitChannel 
     this.mutex <- true 
    } 
    <-this.mutex 
    L1: for { 
     select { 
      case f := <-this.addFunc: 
       this.functions = append(this.functions,f) 
      default: break L1 
     } 
    } 
    if len(this.functions) != 0 { 
     this.functions[0]() 
     if len(this.functions) >= 2 { 
      this.functions = this.functions[1:] 
     } else { 
      this.functions = []func(){} 
     } 
    } else { 
     (<-this.addFunc)() 
    } 
} 
func (this *eventLoop) CurrentTick (f func()) { 
    this.mutex <- true 
    this.threads += 1 
    <-this.mutex 
    go func() { 
     f() 
     this.mutex <- true 
     this.threads -= 1 
     <-this.mutex 
     this.waitChannel <- true 
    }() 
} 
func NewEventLoop() *eventLoop { 
    funcs := make(chan func(),3) 
    loop := &eventLoop{ 
     make([]func(),0,15), /*functions*/ 
     funcs, /*addFunc*/ 
     make(chan bool, 1), /*mutex for threads*/ 
     0, /*Number of threads*/ 
     make(chan bool,0), /*The "wait" channel*/ 
     make(chan bool,1), 
    } 
    go func(){ 
     for { loop.tick() } 
    }() 
    return loop 
} 

참고 : 여전히 많은 문제가 있습니다.

관련 문제