11//! GenServer trait and structs to create an abstraction similar to Erlang gen_server.
22//! See examples/name_server for a usage example.
3- use spawned_rt:: threads:: { self as rt, mpsc, oneshot} ;
3+ use spawned_rt:: threads:: { self as rt, mpsc, oneshot, CancellationToken } ;
44use std:: {
55 fmt:: Debug ,
66 panic:: { catch_unwind, AssertUnwindSafe } ,
@@ -11,20 +11,26 @@ use crate::error::GenServerError;
1111#[ derive( Debug ) ]
1212pub struct GenServerHandle < G : GenServer + ' static > {
1313 pub tx : mpsc:: Sender < GenServerInMsg < G > > ,
14+ cancellation_token : CancellationToken ,
1415}
1516
1617impl < G : GenServer > Clone for GenServerHandle < G > {
1718 fn clone ( & self ) -> Self {
1819 Self {
1920 tx : self . tx . clone ( ) ,
21+ cancellation_token : self . cancellation_token . clone ( ) ,
2022 }
2123 }
2224}
2325
2426impl < G : GenServer > GenServerHandle < G > {
2527 pub ( crate ) fn new ( gen_server : G ) -> Self {
2628 let ( tx, mut rx) = mpsc:: channel :: < GenServerInMsg < G > > ( ) ;
27- let handle = GenServerHandle { tx } ;
29+ let cancellation_token = CancellationToken :: new ( ) ;
30+ let handle = GenServerHandle {
31+ tx,
32+ cancellation_token,
33+ } ;
2834 let handle_clone = handle. clone ( ) ;
2935 // Ignore the JoinHandle for now. Maybe we'll use it in the future
3036 let _join_handle = rt:: spawn ( move || {
@@ -69,18 +75,18 @@ pub enum GenServerInMsg<G: GenServer> {
6975}
7076
7177pub enum CallResponse < G : GenServer > {
72- Reply ( G , G :: OutMsg ) ,
78+ Reply ( G :: OutMsg ) ,
7379 Unused ,
7480 Stop ( G :: OutMsg ) ,
7581}
7682
77- pub enum CastResponse < G : GenServer > {
78- NoReply ( G ) ,
83+ pub enum CastResponse {
84+ NoReply ,
7985 Unused ,
8086 Stop ,
8187}
8288
83- pub trait GenServer : Send + Sized + Clone {
89+ pub trait GenServer : Send + Sized {
8490 type CallMsg : Clone + Send + Sized ;
8591 type CastMsg : Clone + Send + Sized ;
8692 type OutMsg : Send + Sized ;
@@ -101,16 +107,16 @@ pub trait GenServer: Send + Sized + Clone {
101107 handle : & GenServerHandle < Self > ,
102108 rx : & mut mpsc:: Receiver < GenServerInMsg < Self > > ,
103109 ) -> Result < ( ) , GenServerError > {
104- match self . init ( handle) {
105- Ok ( new_state) => {
106- new_state. main_loop ( handle, rx) ?;
107- Ok ( ( ) )
108- }
110+ let mut cancellation_token = handle. cancellation_token . clone ( ) ;
111+ let res = match self . init ( handle) {
112+ Ok ( new_state) => Ok ( new_state. main_loop ( handle, rx) ?) ,
109113 Err ( err) => {
110114 tracing:: error!( "Initialization failed: {err:?}" ) ;
111115 Err ( GenServerError :: Initialization )
112116 }
113- }
117+ } ;
118+ cancellation_token. cancel ( ) ;
119+ res
114120 }
115121
116122 /// Initialization function. It's called before main loop. It
@@ -126,90 +132,82 @@ pub trait GenServer: Send + Sized + Clone {
126132 rx : & mut mpsc:: Receiver < GenServerInMsg < Self > > ,
127133 ) -> Result < ( ) , GenServerError > {
128134 loop {
129- let ( new_state, cont) = self . receive ( handle, rx) ?;
130- if !cont {
135+ if !self . receive ( handle, rx) ? {
131136 break ;
132137 }
133- self = new_state;
134138 }
135139 tracing:: trace!( "Stopping GenServer" ) ;
136140 Ok ( ( ) )
137141 }
138142
139143 fn receive (
140- self ,
144+ & mut self ,
141145 handle : & GenServerHandle < Self > ,
142146 rx : & mut mpsc:: Receiver < GenServerInMsg < Self > > ,
143- ) -> Result < ( Self , bool ) , GenServerError > {
147+ ) -> Result < bool , GenServerError > {
144148 let message = rx. recv ( ) . ok ( ) ;
145149
146- // Save current state in case of a rollback
147- let state_clone = self . clone ( ) ;
148-
149- let ( keep_running, new_state) = match message {
150+ let keep_running = match message {
150151 Some ( GenServerInMsg :: Call { sender, message } ) => {
151- let ( keep_running, new_state, response) =
152- match catch_unwind ( AssertUnwindSafe ( || self . handle_call ( message, handle) ) ) {
153- Ok ( response) => match response {
154- CallResponse :: Reply ( new_state, response) => {
155- ( true , new_state, Ok ( response) )
156- }
157- CallResponse :: Stop ( response) => ( false , state_clone, Ok ( response) ) ,
158- CallResponse :: Unused => {
159- tracing:: error!( "GenServer received unexpected CallMessage" ) ;
160- ( false , state_clone, Err ( GenServerError :: CallMsgUnused ) )
161- }
162- } ,
163- Err ( error) => {
164- tracing:: trace!(
165- "Error in callback, reverting state - Error: '{error:?}'"
166- ) ;
167- ( true , state_clone, Err ( GenServerError :: Callback ) )
152+ let ( keep_running, response) = match catch_unwind ( AssertUnwindSafe ( || {
153+ self . handle_call ( message, handle)
154+ } ) ) {
155+ Ok ( response) => match response {
156+ CallResponse :: Reply ( response) => ( true , Ok ( response) ) ,
157+ CallResponse :: Stop ( response) => ( false , Ok ( response) ) ,
158+ CallResponse :: Unused => {
159+ tracing:: error!( "GenServer received unexpected CallMessage" ) ;
160+ ( false , Err ( GenServerError :: CallMsgUnused ) )
168161 }
169- } ;
162+ } ,
163+ Err ( error) => {
164+ tracing:: trace!( "Error in callback, reverting state - Error: '{error:?}'" ) ;
165+ ( true , Err ( GenServerError :: Callback ) )
166+ }
167+ } ;
170168 // Send response back
171169 if sender. send ( response) . is_err ( ) {
172170 tracing:: trace!( "GenServer failed to send response back, client must have died" )
173171 } ;
174- ( keep_running, new_state )
172+ keep_running
175173 }
176174 Some ( GenServerInMsg :: Cast { message } ) => {
177175 match catch_unwind ( AssertUnwindSafe ( || self . handle_cast ( message, handle) ) ) {
178176 Ok ( response) => match response {
179- CastResponse :: NoReply ( new_state ) => ( true , new_state ) ,
180- CastResponse :: Stop => ( false , state_clone ) ,
177+ CastResponse :: NoReply => true ,
178+ CastResponse :: Stop => false ,
181179 CastResponse :: Unused => {
182180 tracing:: error!( "GenServer received unexpected CastMessage" ) ;
183- ( false , state_clone )
181+ false
184182 }
185183 } ,
186184 Err ( error) => {
187185 tracing:: trace!( "Error in callback, reverting state - Error: '{error:?}'" ) ;
188- ( true , state_clone )
186+ true
189187 }
190188 }
191189 }
192190 None => {
193191 // Channel has been closed; won't receive further messages. Stop the server.
194- ( false , self )
192+ false
195193 }
196194 } ;
197- Ok ( ( new_state , keep_running) )
195+ Ok ( keep_running)
198196 }
199197
200198 fn handle_call (
201- self ,
199+ & mut self ,
202200 _message : Self :: CallMsg ,
203201 _handle : & GenServerHandle < Self > ,
204202 ) -> CallResponse < Self > {
205203 CallResponse :: Unused
206204 }
207205
208206 fn handle_cast (
209- self ,
207+ & mut self ,
210208 _message : Self :: CastMsg ,
211209 _handle : & GenServerHandle < Self > ,
212- ) -> CastResponse < Self > {
210+ ) -> CastResponse {
213211 CastResponse :: Unused
214212 }
215213}
0 commit comments