I have a problem with the behavior switch model.
I have a simple receive actor with 2 behaviors: Ready & DoJob.
The Ready one contains a message handler plus one instruction I need to be evaluated at each behavior switch (cpt++).
Below is the code of the actor:
public class BecomeUnbecome : ReceiveActor
{
private int cpt=0;
public BecomeUnbecome()
{
this.Become(this.Ready);
}
public void Ready()
{
cpt++;
Receive<BeginWork>(msg =>
{
Console.WriteLine($"Go and work!");
BecomeStacked(this.DoJob);
});
}
public void DoJob()
{
Receive<Work>(msg =>
{
Console.WriteLine("Start working...");
Console.WriteLine($"Counter: {cpt}\nWork done\n");
UnbecomeStacked();
});
}
}
The main code is:
int counter = 0;
while (counter < 10)
{
actor.Tell(new BeginWork());
actor.Tell(new Work());
counter++;
}
The program execution shows cpt++ in Ready() is evaluated once next to the call to Become in the constructor.
I cannot find any reasonable workaround to that.
Does anyone have any idea ?
Related
I'm sorry I'm sure this is one of the most frequently asked questions about angular, and I found a ton but nothing's helping me here. I got a simple Observable - subscribe relationship with a variable.
my Service:
activeRoom: number = 0; // we're starting in room 0
/* get the roomnumber from open-rooms to chat-window */
getActiveRoom(): Observable<number> {
return of(this.activeRoom);
}
my component:
constructor(
private activeRoomService: ActiveRoomService){}
ngOnInit() {
/* Observe if we're changing rooms */
this.activeRoomService.getActiveRoom().subscribe(newActiveRoom => {
this.activeRoomChat = []; // clear the message board
this.activeRoom = newActiveRoom;
});
}
click(){
console.log("the following line doesn't work");
console.log(this.activeRoom);
console.log("the following line does work")
console.log(this.activeRoomService.activeRoom);
}
I obviously can't update my component with a click every time, so option b is no option :D
What's the blatantly obvious thing I'm missing here?
Here's a working example.
Service:
private userArray: User[] = [];
getUserArray(): Observable<User[]>{
return of(this.userArray);
}
component:
constructor(private backend: BackendService) {}
ngOnInit() {
this.backend.getUserArray().subscribe(user => {
this.userlist = user;
// console.log(user);
});
Can someone please point a really really big red arrow to the thing I'm missing here?
Changed
activeRoom: number = 0;
getActiveRoom(): Observable<number> {
return of(this.activeRoom);
}
setActiveRoom(roomID): void {
this.activeRoom = roomID;
}
to:
activeRoom: Subject<number> = new Subject;
public getActiveRoom(): Observable<number> {
return this.activeRoom.asObservable();
}
public setActiveRoom(roomID): void {
this.activeRoom.next(roomID);
}
and it works. To be honest, I have no idea why or what changed, but I'm happy it works :D
I have a function (lets call it function A) that 0 to many threads can access it (at the same time, no shared resources). At any given time, the user can use to stop the process. The stop functionality needs to make sure that there are threads accessing function A, so that a graceful shutdown can be performed. Is there a native procedure to do so?
What I was going to do is have an InterlockedIncrement an integer everytime function A is called (and a corresponding InterlockedDecrement on said integer when function A exists). When an InterlockedDecrement takes place, it checks the value of the integer, if it's set to zero, a event is set to signalled. If the value is not zero, the event is set to nonsignalled.
This makes sense in my mind, but I'm curious whether there is a more native structure / functionality adapted to do so.
I still have to thing about the fact the "stop" function may get starved (in the sense, the said integer may never be set to zero). A sidenote: when the stop event takes place, the InterlockedIncrement process shall be stopped, to reduce said starvation.
what you need and want implement is called Run-Down Protection. unfortunately it supported only in kernel mode, but not hard implement it yourself in user mode too.
the simplest implementation is next:
HANDLE ghStopEvent;
LONG gLockCount = 1;
BOOLEAN bStop = FALSE;
void unlock()
{
if (!InterlockedDecrement(&gLockCount)) SetEvent(ghStopEvent);
}
BOOL lock()
{
LONG Value = gLockCount, NewValue;
for ( ; !bStop && Value; Value = NewValue)
{
NewValue = InterlockedCompareExchange(&gLockCount, Value + 1, Value);
if (NewValue == Value) return TRUE;
}
return FALSE;
}
void funcA();
void UseA()
{
if (lock())
{
funcA();
unlock();
}
}
and when you want begin rundown - once call
bStop = TRUE; unlock();
how you can see lock function is interlocked increment gLockCount on 1 but only if it not 0.
in kernel mode you can call instead
EX_RUNDOWN_REF gRunRef;
void UseA()
{
if (ExAcquireRundownProtection(&gRunRef))
{
funcA();
ExReleaseRundownProtection(&gRunRef)
}
}
and on place final unlock - ExWaitForRundownProtectionRelease
some more complex and scalable implementation of rundown-protection:
#define RUNDOWN_INIT_VALUE 0x80000000
#define RUNDOWN_COMPLETE_VALUE 0
class __declspec(novtable) RUNDOWN_REF
{
LONG _LockCount;
protected:
virtual void RundownCompleted() = 0;
public:
BOOL IsRundownBegin()
{
return 0 <= _LockCount;
}
void Reinit()
{
if (InterlockedCompareExchange(&_LockCount, RUNDOWN_INIT_VALUE, RUNDOWN_COMPLETE_VALUE) != RUNDOWN_COMPLETE_VALUE)
{
__debugbreak();
}
}
RUNDOWN_REF()
{
_LockCount = RUNDOWN_INIT_VALUE;
}
BOOL AcquireRundownProtection()
{
LONG Value = _LockCount, NewValue;
for ( ; Value < 0; Value = NewValue)
{
NewValue = InterlockedCompareExchange(&_LockCount, Value + 1, Value);
if (NewValue == Value) return TRUE;
}
return FALSE;
}
void ReleaseRundownProtection()
{
if (RUNDOWN_COMPLETE_VALUE == InterlockedDecrement(&_LockCount))
{
RundownCompleted();
}
}
void BeginRundown()
{
if (AcquireRundownProtection())
{
_interlockedbittestandreset(&_LockCount, 31);
ReleaseRundownProtection();
}
}
};
and use it like:
class MY_RUNDOWN_REF : public RUNDOWN_REF
{
HANDLE _hEvent;
virtual void RundownCompleted()
{
SetEvent(_hEvent);
}
// ...
} gRunRef;
void UseA()
{
if (gRunRef.AcquireRundownProtection())
{
funcA();
gRunRef.ReleaseRundownProtection();
}
}
and when you want stop:
gRunRef.BeginRundown();// can be safe called multiple times
// wait on gRunRef._hEvent here
interesting that in kernel exist else one (more old - from win2000, when rundown protection from xp) api Remove Locks. it do almost the same. different only in internal implementation and usage. with remove locks code will be look like this:
IO_REMOVE_LOCK gLock;
void UseA()
{
if (0 <= IoAcquireRemoveLock(&gLock, 0))
{
funcA();
IoReleaseRemoveLock(&gLock, 0);
}
}
and when we want stop - call
IoAcquireRemoveLock(&gLock, 0);
IoReleaseRemoveLockAndWait(&gLock, 0);
my first code spinet by implementation near remove locks implementation, when second near rundown-protection implementation. but by sense both do the same
I'm learning RX and would like to use Console.ReadLine as a source for observable sequences.
I know that I can create "IEnumerable" using "yield return", but for my concrete use case I've decided to create a C# event, so that potentially many observers will be able to share the same keyboard input.
Here is my code:
class Program
{
private delegate void OnNewInputLineHandler(string line);
private static event OnNewInputLineHandler OnNewInputLineEvent = _ => {};
static void Main(string[] args)
{
Task.Run((Action) GetInput);
var input = ConsoleInput();
input.Subscribe(s=>Console.WriteLine("1: " + s));
Thread.Sleep(30000);
}
private static void GetInput()
{
while (true)
OnNewInputLineEvent(Console.ReadLine());
}
private static IObservable<string> ConsoleInput()
{
return Observable.Create<string>(
(IObserver<string> observer) =>
{
OnNewInputLineHandler h = observer.OnNext;
OnNewInputLineEvent += h;
return Disposable.Create(() => { OnNewInputLineEvent -= h; });
});
}
}
My problem - when I run the GetInput method as it is shown above, the very first input line is not sent to the sequence (but it is sent to the event handler).
However, if I replace it with the following version, everything works as expected:
private static void GetInput()
{
while (true)
{
var s = Console.ReadLine();
OnNewInputLineEvent(s);
}
}
Could someone shed some light on why this might happen?
You're trying to make life difficult for yourself. There is almost always a way to make things simple with Rx. It's just a matter of learning to think more functionally rather than procedurally.
This is all you need:
class Program
{
static void Main(string[] args)
{
var subscription = ConsoleInput().Subscribe(s => Console.WriteLine("1: " + s));
Thread.Sleep(30000);
subscription.Dispose();
}
private static IObservable<string> ConsoleInput()
{
return
Observable
.FromAsync(() => Console.In.ReadLineAsync())
.Repeat()
.Publish()
.RefCount()
.SubscribeOn(Scheduler.Default);
}
}
This lets multiple subscribers share the one input through the .Publish().RefCount(). And the .SubscribeOn(Scheduler.Default) pushes the subscription out to a new thread - without it you block on a subscription.
If you move Task.Run((Action) GetInput); to after the subscription your code will work as desired. This is because in your original version, the first call of OnNewInputEvent(Console.ReadLine()) is run before you've hooked OnNewInputLineEvent to the observer.OnNext.
i have a doubt..
i would like to create a function and it will look like this...
public class A //this is just a class file
{
function dowork()
{
//work 1
INPUT = here in this line it should call a delegate function or raise event etc...
//work 2 using INPUT
}
}
public class B
{
function myfn()
{
A objA = new A();
objA.dowork();
}
}
In the "Class A" we will raise event or so & it will display a windows form to user and then user will input some value & we need to return that value to Class A -> dowork method.... then only we should continue "work 2"
this should also support multi threading... anyone have idea how we can implement this??
thanks :)
You can use ManulResetEvent for this purpose: You run your input form and when it done that form set the event so you can catch it from A.dowork method. While the input in action you run the infinite loop, check event state and process application event to make you app responsible in this time:
public class A //this is just a class file
{
private ManualResetEvent _event;
public void dowork()
{
//work 1
_event = new ManualResetEvent(false);
//INPUT = here in this ...
Worker worker = new Worker();
worker.DoInput(_event);
while(true)
{
if(_event.WaitOne())
break;
Application.DoEvents();
}
//work 2 using INPUT
}
}
class Worker
{
private ManualResetEvent _event;
public void DoInput(ManualResetEvent #event)
{
_event = #event;
// Show input form here.
// When it done, you call: _event.Set();
}
}
Also, I suggest you (if you can) use Async library (it is available as a standalone setup). There you can implement it in much more straightforward way:
public class A //this is just a class file
{
public async void dowork()
{
//work 1
//INPUT = here in this ...
Worker worker = new Worker();
wait worker.DoInput();
//work 2 using INPUT
}
}
class Worker
{
public async void DoInput()
{
InputForm form = new InputForm();
wait form.ShowInput();
}
}
public class B
{
async void myfn()
{
A objA = new A();
wait objA.dowork();
}
}
As you see you just wait while other piece of code get executed without any UI locking and events.
I can provide deeper explanation of how async/wait works here if you need.
I recently finished a 6-month internship at a company that uses C# for the most part of their programming. During this time I first used and got accustomed to the C# way of doing events. Like shown below:
acc.AccountBalanceLow += new AccountBalanceDelegate(atm.AccountToLow);
acc.AccountBalanceLow +=new AccountBalanceDelegate(atm.AccountToLowAgain);
Does D support such constructs? I'd imagine one could be created by the user by using operator overloading, but I'm not entirely sure. If it's not possible what would then be a common excepted way of doing it then?
The equivalent construct in D is to use Signals and Slots. This is a different means of implementing the Observer Pattern, which is effectively what a C# event does.
D (and C++) use an analogous pattern called signals and slots.
If you're feeling the need to use the C# style-events instead of signals and slots, they're extremely simple to implement:
module fluidity.core.event;
class Event {
alias void delegate(EventArgs) handler_t;
handler_t[] handlers;
Object owner;
this() {}
this(Object o) { owner = o; }
void attach(handler_t handler) {
if (handler)
handlers ~= handler;
}
void detach(handler_t handler) {
int i = -1;
foreach (j, h; handlers)
{
if (h is handler)
{
i = j;
break;
}
}
if (i > -1)
handlers = handlers[0..i] ~ handlers[i+1..$];
}
void raise() { raise(new EventArgs(owner)); }
void raise(EventArgs e) {
// call all handlers
foreach (handler; handlers)
{
if (handler)
handler(e);
}
}
void opAddAssign(handler_t handler) {
attach(handler);
}
void opSubAssign(handler_t handler) {
detach(handler);
}
}
class EventArgs {
Object source;
bool handled;
void handle() { handled = true; }
this() {}
this(Object s) {
source = s;
}
}
Here is an example of c# style events using signals, slots, and a templates:
events.d:
import std.signals;
class Event(T...){
mixin Signal!(T);
void broadcast(T args){
emit(args);
}
void opAddAssign(slot_t slot){
connect(slot);
}
void opSubAssign(slot_t slot) {
disconnect(slot);
}
}
declaration:
public Event!(int) onSomeEventOfInt;
public Event!(string, int) onSomeEventOfStringAndInt;
instantiation:
this.onSomeEventOfInt = new Event!(int)();
this.onSomeEventOfStringAndInt = new Event!(string, int)();
fire event:
int i = 4;
string str = "hello";
this.onSomeEventOfInt.broadcast(i);
this.onSomeEventOfStringAndInt.broadcast(str, 4);
observer registration:
obj1.onSomeEventOfInt += &handleEventOfInt
obj1.onSomeEventOfStringAndInt += &handleEventOfStringAndInt
void handleEventOfInt(int g)
{ /*do something */ }
void handleEventOfStringAndInt(string str, int g)
{ /*do something */ }
Check out DFL's event system. It works EXACTLY the same way as C# .NET.
DFL Event Example
Download DFL, grab the events module and use it the way you like. I modified it to use variadic template arguments. This gives maximum flexibility.
http://www.dprogramming.com/dfl098.zip