go-hep.org/x/hep@v0.38.1/fwk/cmd/fwk-cpu-cruncher/cruncher.go (about)

     1  // Copyright ©2017 The go-hep Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package main
     6  
     7  import (
     8  	"fmt"
     9  	"reflect"
    10  	"time"
    11  
    12  	"go-hep.org/x/hep/fwk"
    13  )
    14  
    15  type CPUCruncher struct {
    16  	fwk.TaskBase
    17  
    18  	cpuch chan int64
    19  	quit  chan struct{}
    20  
    21  	inputs  []string
    22  	outputs []string
    23  	cpus    []int64
    24  }
    25  
    26  func (tsk *CPUCruncher) Configure(ctx fwk.Context) error {
    27  	var err error
    28  
    29  	for _, input := range tsk.inputs {
    30  		if input == "" {
    31  			continue
    32  		}
    33  		err = tsk.DeclInPort(input, reflect.TypeOf(int64(0)))
    34  		if err != nil {
    35  			return err
    36  		}
    37  	}
    38  
    39  	for _, output := range tsk.outputs {
    40  		if output == "" {
    41  			continue
    42  		}
    43  		err = tsk.DeclOutPort(output, reflect.TypeOf(int64(0)))
    44  		if err != nil {
    45  			return err
    46  		}
    47  	}
    48  
    49  	if len(tsk.cpus) <= 0 {
    50  		msg := ctx.Msg()
    51  		msg.Errorf("invalid cpu-timings list: %v\n", tsk.cpus)
    52  		return fmt.Errorf("invalid cpu-timings")
    53  	}
    54  
    55  	return err
    56  }
    57  
    58  func (tsk *CPUCruncher) StartTask(ctx fwk.Context) error {
    59  	var err error
    60  
    61  	go func() {
    62  		i := 0
    63  		n := len(tsk.cpus)
    64  		for {
    65  			select {
    66  			case <-tsk.quit:
    67  				return
    68  			default:
    69  				if i >= n {
    70  					i = 0
    71  				}
    72  				v := tsk.cpus[i]
    73  				i++
    74  				tsk.cpuch <- v
    75  			}
    76  		}
    77  	}()
    78  
    79  	return err
    80  }
    81  
    82  func (tsk *CPUCruncher) StopTask(ctx fwk.Context) error {
    83  	var err error
    84  	go func() { tsk.quit <- struct{}{} }()
    85  	return err
    86  }
    87  
    88  func (tsk *CPUCruncher) Process(ctx fwk.Context) error {
    89  	var err error
    90  	store := ctx.Store()
    91  	for _, input := range tsk.inputs {
    92  		_, err = store.Get(input)
    93  		if err != nil {
    94  			return err
    95  		}
    96  	}
    97  
    98  	cpu := <-tsk.cpuch
    99  	time.Sleep(time.Duration(cpu) * time.Microsecond)
   100  
   101  	for _, output := range tsk.outputs {
   102  		err = store.Put(output, cpu)
   103  		if err != nil {
   104  			return err
   105  		}
   106  	}
   107  
   108  	return err
   109  }
   110  
   111  func newCPUCruncher(typ, name string, mgr fwk.App) (fwk.Component, error) {
   112  	var err error
   113  
   114  	tsk := &CPUCruncher{
   115  		TaskBase: fwk.NewTask(typ, name, mgr),
   116  		cpuch:    make(chan int64),
   117  		quit:     make(chan struct{}),
   118  		inputs:   make([]string, 0),
   119  		outputs:  make([]string, 0),
   120  		cpus:     make([]int64, 0),
   121  	}
   122  
   123  	err = tsk.DeclProp("Inputs", &tsk.inputs)
   124  	if err != nil {
   125  		return nil, err
   126  	}
   127  
   128  	err = tsk.DeclProp("Outputs", &tsk.outputs)
   129  	if err != nil {
   130  		return nil, err
   131  	}
   132  
   133  	err = tsk.DeclProp("CPU", &tsk.cpus)
   134  	if err != nil {
   135  		return nil, err
   136  	}
   137  
   138  	return tsk, err
   139  }
   140  
   141  func init() {
   142  	fwk.Register(reflect.TypeOf(CPUCruncher{}), newCPUCruncher)
   143  }