func (p *proc) addHistoryEntry(ts time.Time, status string) {
	p.history.PushBack(&historyEntry{
		ts:     ts,
		status: status,
	})
}
addHistoryEntry pushes a new entry to the processes' history, assuming the
lock is already held.
package pm
import (
	"container/list"
	"errors"
	"sync"
	"time"
)
type Proclist struct {
	mu    sync.RWMutex
	procs map[string]*proc
	opts  ProclistOpts
}
type ProclistOpts struct {
	StopCancelPanic bool  
	ForbidCancel    bool  
}
type ProcOpts struct {
	StopCancelPanic bool  
	ForbidCancel    bool  
}
type proc struct {
	mu      sync.RWMutex
	id      string
	attrs   map[string]interface{}
	history list.List
	cancel  struct {
		isPending bool
		message   string
	}
	opts ProcOpts
}
type historyEntry struct {
	ts     time.Time
	status string
}
var (
	ErrForbidden     = errors.New("forbidden")
	ErrNoSuchProcess = errors.New("no such process")
)
func (pl *Proclist) Options() ProclistOpts {
	pl.mu.RLock()
	defer pl.mu.RUnlock()
	return pl.opts
}
func (pl *Proclist) SetOptions(opts ProclistOpts) {
	pl.mu.Lock()
	defer pl.mu.Unlock()
	pl.opts = opts
}
func (pl *Proclist) Start(id string, opts *ProcOpts, attrs *map[string]interface{}) {
	if opts == nil {
		opts = &ProcOpts{
			StopCancelPanic: pl.opts.StopCancelPanic,
			ForbidCancel:    pl.opts.ForbidCancel,
		}
	}
	p := &proc{
		id:   id,
		opts: *opts,
	}
	if attrs != nil {
		p.attrs = *attrs
	} else {
		p.attrs = make(map[string]interface{})
	}
	p.addHistoryEntry(time.Now(), "init")
	pl.mu.Lock()
	if pl.procs == nil {
		pl.procs = make(map[string]*proc)
	}
	pl.procs[id] = p
	pl.mu.Unlock()
}
func (pl *Proclist) SetAttribute(id, name string, value interface{}) {
	pl.mu.RLock()
	p, present := pl.procs[id]
	pl.mu.RUnlock()
	if present {
		p.mu.Lock()
		defer p.mu.Unlock()
		p.attrs[name] = value
	}
}
func (pl *Proclist) DelAttribute(id, name string) {
	pl.mu.RLock()
	p, present := pl.procs[id]
	pl.mu.RUnlock()
	if present {
		p.mu.Lock()
		defer p.mu.Unlock()
		delete(p.attrs, name)
	}
}
type CancelErr string
func (e CancelErr) Error() string {
	return string(e)
}
func (p *proc) doCancel() {
	message := "killed"
	if len(p.cancel.message) > 0 {
		message += ": " + p.cancel.message
	}
	panic(CancelErr(message))
}