thespis_impl 0.3.0

Reference implementation for the thespis actor model
Documentation
// Tested:
//
// - ✔ Spawn mailbox for actor that is !Send and !Sync
// - ✔ Spawn mailbox for actor that is Send and Sync but using the local methods
// - ✔ Manually spawn mailbox for actor that is !Send and !Sync
// - ✔ Manually spawn mailbox for actor that is Send and Sync but using the local methods
//
#![ cfg(not( target_arch = "wasm32" )) ]


mod common;

use
{
	common  :: { actors::*, import::*                     } ,
	futures :: { task::LocalSpawnExt, executor::LocalPool } ,
};



#[test]
//
fn not_send_actor() -> Result<(), DynError >
{
	let mut pool  = LocalPool::new();
	let     exec  = pool.spawner();
	let     exec2 = exec.clone();

	let program = async move
	{

		// If we inline this in the next statement, it actually compiles with rt::spawn( program ) instead
		// of spawn_local.
		//
		let mut addr = Addr::builder( "not_send_actor" ).spawn_local( SumNoSend::new(5), &exec2 ).expect( "start mailbox" );

		addr.send( Add( 10 ) ).await.expect( "Send" );

		let result = addr.call( Show{} ).await.expect( "Call failed" );


		assert_eq!( 15, result );
	};

	exec.spawn_local( program )?;
	pool.run();

	Ok(())
}




#[test]
//
fn send_actor() -> Result<(), DynError >
{
	let mut pool  = LocalPool::new();
	let     exec  = pool.spawner();
	let     exec2 = exec.clone();

	let program = async move
	{
		// If we inline this in the next statement, it actually compiles with rt::spawn( program ) instead
		// of spawn_local.
		//
		let mut addr = Addr::builder( "send_actor" ).spawn_local( Sum(5), &exec2 ).expect( "spawn actor mailbox" );

		addr.send( Add( 10 ) ).await.expect( "Send failed" );

		let result = addr.call( Show{} ).await.expect( "Call failed" );

		assert_eq!( 15, result );
	};

	exec.spawn_local( program )?;
	pool.run();

	Ok(())
}



#[test]
//
fn test_manually_not_send_actor() -> Result<(), DynError >
{
	let mut pool  = LocalPool::new();
	let     exec  = pool.spawner();
	let     exec2 = exec.clone();

	let program = async move
	{
		let actor = SumNoSend::new(5);

		let (tx, rx) = mpsc::unbounded()                                         ;
		let mb       = Mailbox::new( "SumNoSend", Box::new(rx) )                 ;
		let tx       = Box::new(tx.sink_map_err( |e| Box::new(e) as DynError ))  ;
		let mut addr = mb.addr( tx )                                             ;

		exec2.spawn_local( async { mb.start_local( actor ).await; } ).expect( "spawn actor mailbox" );

		addr.send( Add( 10 ) ).await.expect( "Send failed" );

		let result = addr.call( Show{} ).await.expect( "Call failed" );

		assert_eq!( 15, result );
	};

	exec.spawn_local( program )?;
	pool.run();

	Ok(())
}




#[test]
//
fn test_manually_send_actor() -> Result<(), DynError >
{
	let mut pool  = LocalPool::new();
	let     exec  = pool.spawner();
	let     exec2 = exec.clone();

	let program = async move
	{
		// If we inline this in the next statement, it actually compiles with rt::spawn( program ) instead
		// of spawn_local.
		//
		let actor    = Sum(5)                                                    ;
		let (tx, rx) = mpsc::unbounded()                                         ;
		let mb       = Mailbox::new( "Sum", Box::new(rx) )                       ;
		let tx       = Box::new(tx.sink_map_err( |e| Box::new(e) as DynError ))  ;
		let mut addr = mb.addr( tx )                                             ;

		exec2.spawn_local( async { mb.start_local( actor ).await; } ).expect( "spawn actor mailbox" );

		addr.send( Add( 10 ) ).await.expect( "Send failed" );

		let result = addr.call( Show{} ).await.expect( "Call failed" );

		assert_eq!( 15, result );
	};

	exec.spawn_local( program )?;
	pool.run();

	Ok(())
}