package actor // Actor serializes calls to a handler. By default the sender consumes messages // inline; WithDispatcher can provide another execution policy. An Actor must be // created with New and must not be copied after first use. type Actor[T any] struct { mailbox *mailbox[T] } // New creates an Actor. A nil handler, nil option, invalid dispatcher, or // nonpositive fixed capacity or batch size causes a panic. The default // dispatcher runs inline and does not start any goroutine. func New[T any](handler func(T), opts ...Option[T]) *Actor[T] { if handler == nil { panic("actor: nil handler") } c := configure(opts) return &Actor[T]{mailbox: newMailbox( newQueue[T](c.fixedCapacity), invoker[T]{handler: handler, onPanic: c.onPanic}, c.batchSize, c.dispatcher, )} } // Send publishes a message. The sender that obtains consumption ownership // schedules a task to drain the mailbox. By default it runs synchronously; // a custom dispatcher may run it asynchronously. Other senders only enqueue. // Returning does not guarantee message completion. Sending to the same Actor // from its handler enqueues without reentering it. Concurrent sends are ordered // by their successful publication CAS. func (a *Actor[T]) Send(message T) { a.mailbox.send(message) }