www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Can someone give me a little program design advice please?

reply "Gary Willoughby" <dev kalekold.net> writes:
I'm writing a little program in D to perform some database 
operations and have a small question about design.

Part of my program watches a log file for changes and this 
involves code which is wrapped up in a class. So the usage is 
something like this:

auto fileWatcher = new FileWatcher(fileName);
fileWatcher.onChange(delegate);
fileWatcher.start();

Once the start method is called a loop is entered within the 
class and the file is watched. Changes are handle through calling 
the registered delegate. The loop uses different watch methods 
for different platforms.

What i need to be able to do is to stop the current watch and 
change the watched file.

Because this is in an infinite loop, i can't check externally 
i.e. outside of the class, if i need to break from the loop 
simply because control never returns to the caller of the start() 
method.

Am i missing something simple here? Any advice is welcome. I 
thought about threading and message passing but that's maybe 
overkill for something as simple as this?

I've also put this question on stackoverflow here

http://stackoverflow.com/questions/17134809/how-to-check-global-events-inside-an-infinite-loop-within-a-class
Jun 16 2013
next sibling parent reply "Regan Heath" <regan netmail.co.nz> writes:
On Sun, 16 Jun 2013 16:27:27 +0100, Gary Willoughby <dev kalekold.net>  
wrote:

 I'm writing a little program in D to perform some database operations  
 and have a small question about design.

 Part of my program watches a log file for changes and this involves code  
 which is wrapped up in a class. So the usage is something like this:

 auto fileWatcher = new FileWatcher(fileName);
 fileWatcher.onChange(delegate);
 fileWatcher.start();

 Once the start method is called a loop is entered within the class and  
 the file is watched. Changes are handle through calling the registered  
 delegate. The loop uses different watch methods for different platforms.

 What i need to be able to do is to stop the current watch and change the  
 watched file.

 Because this is in an infinite loop, i can't check externally i.e.  
 outside of the class, if i need to break from the loop simply because  
 control never returns to the caller of the start() method.
I would derive FileWatcher from Thread: http://dlang.org/phobos/core_thread.html#.Thread So, now control does return to the caller - so you can create these in you main control thread before going off to do other things. Note that Thread does not have a stop() method. This is likely because ruthlessly terminating a thread is generally frowned upon. Instead you 'ask' the thread nicely to stop (first). My preferred method of doing this is to have a boolean loop control variable, plus an event. So your main thread loop checks the loop control variable, and when the thread wants to sleep/wait for any reason it waits on the event. In this way you can instantly wake it up by setting the event, and you can instantly stop it by setting the loop control variable and waking it up. e.g. class FileWatcher : Thread { private: bool stopping; <event> sleepEvent; void run() { while (!stopping) { // ..your main loop code here.. // if you need to wait/sleep <wait on sleepEvent> // always check stopping after waiting/sleeping if your loop processes more after this if (stopping) break; // ..more loop code here.. } } public: void stop() { stopping = true; <set the event> } } R -- Using Opera's revolutionary email client: http://www.opera.com/mail/
Jun 17 2013
parent "Gary Willoughby" <dev kalekold.net> writes:
Interesting thanks.
Jun 18 2013
prev sibling parent reply Sean Kelly <sean invisibleduck.org> writes:
On Jun 16, 2013, at 8:27 AM, Gary Willoughby <dev kalekold.net> wrote:

 I'm writing a little program in D to perform some database operations =
and have a small question about design.
=20
 Part of my program watches a log file for changes and this involves =
code which is wrapped up in a class. So the usage is something like = this:
=20
 auto fileWatcher =3D new FileWatcher(fileName);
 fileWatcher.onChange(delegate);
 fileWatcher.start();
=20
 Once the start method is called a loop is entered within the class and =
the file is watched. Changes are handle through calling the registered = delegate. The loop uses different watch methods for different platforms.
=20
 What i need to be able to do is to stop the current watch and change =
the watched file.
=20
 Because this is in an infinite loop, i can't check externally i.e. =
outside of the class, if i need to break from the loop simply because = control never returns to the caller of the start() method.
=20
 Am i missing something simple here? Any advice is welcome. I thought =
about threading and message passing but that's maybe overkill for = something as simple as this? Some form of concurrency is probably what you want here. But be aware = that your delegate may have to be made thread-safe, depending on what it = does. Regan suggested using Thread, and you can use spawn as well: import std.concurrency; import std.conv; import std.datetime; import std.stdio; import core.thread; void main() { auto tid =3D spawn(&fileWatcher, "file0"); foreach (i; 1 .. 5) { Thread.sleep(dur!"msecs"(300)); // sleep for a = bit to simulate work send(tid, "file" ~ to!string(i)); } } void fileWatcher(string fileName) { while (true) { receiveTimeout(dur!"msecs"(0), (string n) =3D> = fileName =3D n); writefln("checking %s", fileName); Thread.sleep(dur!"msecs"(100)); // sleep for a = bit to simulate work } writeln("bye!"); }
Jun 19 2013
parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 06/19/2013 11:46 AM, Sean Kelly wrote:

 			Thread.sleep(dur!"msecs"(300));
Totally unrelated but there has been some positive changes. :) The following is much better: Thread.sleep(300.msecs); Ali
Jun 19 2013
parent Sean Kelly <sean invisibleduck.org> writes:
On Jun 19, 2013, at 12:54 PM, Ali =C7ehreli <acehreli yahoo.com> wrote:

 On 06/19/2013 11:46 AM, Sean Kelly wrote:
=20
 			Thread.sleep(dur!"msecs"(300));
=20 Totally unrelated but there has been some positive changes. :) The =
following is much better:
=20
    Thread.sleep(300.msecs);
Hooray for UFCS!=
Jun 19 2013