Asynchronous timers (without a run loop)
-
I need to use timers in a low level library where I need to specify
asynchronous callbacks to a timer function. I will not have any run
loop so I cannot use NSTimer. Are there any low level timer API to use
instead? I haven't found anything useful (yet) on google nor ADC. I
assume there must exist some Mach or BSD level API:s that can be used?
Any suggestions?
/ PÃ¥hl -
NSRunLoop use to be based on the function select() (it was in GnuStep
anyway), it waits for inputs but also has a single timeout value also,
NSRunLoop works out how long the timeout value should be for the
shortest NSTimer. If you want to wait on multiple timers without using
run NSRunLoop then you will have to implement this kind of
functionality yourself. You can then just use sleep() to make your
thread wait.
On 04/12/2008, at 9:32 PM, PÃ¥hl Melin wrote:> I need to use timers in a low level library where I need to specify
> asynchronous callbacks to a timer function. I will not have any run
> loop so I cannot use NSTimer. Are there any low level timer API to use
> instead? I haven't found anything useful (yet) on google nor ADC. I
> assume there must exist some Mach or BSD level API:s that can be used?
>
> Any suggestions?
>
> / PÃ¥hl -
Yes, I could set up a new thread, handling a list of usleep()
intervals between the actual timer events but it would be very hard to
make a reliable, drift-free timer service, handling lots of timer
events and it would take quite some time to develop a fully functional
and reliable version. I really hope I don't have to...
In the Kernel Programming Guide in ADC, chapter 7, Mach Overview, Time
Management, it says:
"The mach_timespec_t API is deprecated in Mac OS X. The newer and
preferred API is based on timer objects
that in turn use AbsoluteTime as the basic data type. AbsoluteTime is
a machine-dependent type, typically
based on the platform-native time base. Routines are provided to
convert AbsoluteTime values to and from
other data types, such as nanoseconds. Timer objects support
asynchronous, drift-free notification, cancellation,
and premature alarms. They are more efficient and permit higher
resolution than clocks."
Does anyone know about this "new API" or any higher level API build on
it? I sounds like a good candidate for my project.
/ PÃ¥hl
2008/12/4 Nathan Day <nathan_day...>:> NSRunLoop use to be based on the function select() (it was in GnuStep
> anyway), it waits for inputs but also has a single timeout value also,
> NSRunLoop works out how long the timeout value should be for the shortest
> NSTimer. If you want to wait on multiple timers without using run NSRunLoop
> then you will have to implement this kind of functionality yourself. You can
> then just use sleep() to make your thread wait.
>
> On 04/12/2008, at 9:32 PM, PÃ¥hl Melin wrote:
>
>> I need to use timers in a low level library where I need to specify
>> asynchronous callbacks to a timer function. I will not have any run
>> loop so I cannot use NSTimer. Are there any low level timer API to use
>> instead? I haven't found anything useful (yet) on google nor ADC. I
>> assume there must exist some Mach or BSD level API:s that can be used?
>>
>> Any suggestions?
>>
>> / PÃ¥hl
>
> -
Le 4 déc. 08 à 14:00, Påhl Melin a écrit :> Yes, I could set up a new thread, handling a list of usleep()
> intervals between the actual timer events but it would be very hard to
> make a reliable, drift-free timer service, handling lots of timer
> events and it would take quite some time to develop a fully functional
> and reliable version. I really hope I don't have to...
>
> In the Kernel Programming Guide in ADC, chapter 7, Mach Overview, Time
> Management, it says:
>
> "The mach_timespec_t API is deprecated in Mac OS X. The newer and
> preferred API is based on timer objects
> that in turn use AbsoluteTime as the basic data type. AbsoluteTime is
> a machine-dependent type, typically
> based on the platform-native time base. Routines are provided to
> convert AbsoluteTime values to and from
> other data types, such as nanoseconds. Timer objects support
> asynchronous, drift-free notification, cancellation,
> and premature alarms. They are more efficient and permit higher
> resolution than clocks."
>
> Does anyone know about this "new API" or any higher level API build on
> it? I sounds like a good candidate for my project.
>
> / PÃ¥hl
>
> 2008/12/4 Nathan Day <nathan_day...>:
>> NSRunLoop use to be based on the function select() (it was in GnuStep
>> anyway), it waits for inputs but also has a single timeout value
>> also,
>> NSRunLoop works out how long the timeout value should be for the
>> shortest
>> NSTimer. If you want to wait on multiple timers without using run
>> NSRunLoop
>> then you will have to implement this kind of functionality
>> yourself. You can
>> then just use sleep() to make your thread wait.
>>
>> On 04/12/2008, at 9:32 PM, PÃ¥hl Melin wrote:
>>
>>> I need to use timers in a low level library where I need to specify
>>> asynchronous callbacks to a timer function. I will not have any run
>>> loop so I cannot use NSTimer. Are there any low level timer API to
>>> use
>>> instead? I haven't found anything useful (yet) on google nor ADC. I
>>> assume there must exist some Mach or BSD level API:s that can be
>>> used?
>>>
>>> Any suggestions?
>>
If you want to avoid Cocoa, Cocoa-dev is probably not the best mailing
list to ask.
You will have more chance on darwin-dev.
What do you mean by "low-leve" ? What prevent you to use NS classes ?
Is this contraint preventing you to use CoreFoundation ? (which is
low-level IMHO).
If you want lower level primitive, you can use kevent's timers, or if
you want really low-level, there is a mach timer API, but I don't
think it is considere public as the header cannot be found in /usr/
include/mach
Anyway, that's the API used in CoreFoundation for CFTimer and declared
in mk_timer.h (see XNU sources for details). But I wont go this way in
a shipping product. -
2008/12/4 Jean-Daniel Dupas <devlists...>:> If you want to avoid Cocoa, Cocoa-dev is probably not the best mailing list
> to ask.
> You will have more chance on darwin-dev.
I don't want to avoid Cocoa, but I just haven't found any Cocoa class
that supports timers without a run loop. But maybe I need to switch to
darwin-dev.> What do you mean by "low-leve" ? What prevent you to use NS classes ?
> Is this contraint preventing you to use CoreFoundation ? (which is
> low-level IMHO).
Nothing prevents me from using NS classes per se. I will use the
timers in a C++ class and want to get a callback to a normal
functionânot calling a selector on an Objective-C class that most NS
classes would do. And since it's supposed to be the lowest level of my
architecture I want it to be as efficient as possible.
The only problem I have is that I will run the timers on threads
without run loops so both NSTimer and CFRunLoopTimer (I didn't find
any reference information about CFTimer on ADC) are impossible to use.> If you want lower level primitive, you can use kevent's timers, or if you
> want really low-level, there is a mach timer API, but I don't think it is
> considere public as the header cannot be found in /usr/include/mach
In the man page for kevent it says that kevent timers are not
supported ("EVFILT_TIMER This filter is currently unsupported."). I
just assumed that the man page was correct and haven't made any tests.
Are you sure kevent timers are implemented in Mac OS X? When it comes
to Mach timers I wouldn't dare to use that in a commercial product
since Apple seems to ask developers to keep away from Mach.> Anyway, that's the API used in CoreFoundation for CFTimer and declared in
> mk_timer.h (see XNU sources for details). But I wont go this way in a
> shipping product.
Agree... I will keep away from any private API:s.
/ PÃ¥hl -
Le 4 déc. 08 à 15:17, Påhl Melin a écrit :> 2008/12/4 Jean-Daniel Dupas <devlists...>:
>> If you want to avoid Cocoa, Cocoa-dev is probably not the best
>> mailing list
>> to ask.
>> You will have more chance on darwin-dev.
>
> I don't want to avoid Cocoa, but I just haven't found any Cocoa class
> that supports timers without a run loop. But maybe I need to switch to
> darwin-dev.
>
>> What do you mean by "low-leve" ? What prevent you to use NS classes ?
>> Is this contraint preventing you to use CoreFoundation ? (which is
>> low-level IMHO).
>
> Nothing prevents me from using NS classes per se. I will use the
> timers in a C++ class and want to get a callback to a normal
> functionânot calling a selector on an Objective-C class that most NS
> classes would do. And since it's supposed to be the lowest level of my
> architecture I want it to be as efficient as possible.
>
> The only problem I have is that I will run the timers on threads
> without run loops so both NSTimer and CFRunLoopTimer (I didn't find
> any reference information about CFTimer on ADC) are impossible to use.
>
Of course, CFTimer was a shortened form for CFRunLoopTimer.
If you use timer, you need some primitive function that waits until
one timer "trigger". I don't understand what is the difference between
waiting using select, kevent,
or any other primitive and waiting using CFRunLoopRun(). All threads
have a runloop (or create one when needed), so I really don't
understand what is the problem here.
For kevent, I'm surprised the doc say so, it look like it is
implemented (at least in 10.4.11 and 10.5 XNU sources).>> If you want lower level primitive, you can use kevent's timers, or
>> if you
>> want really low-level, there is a mach timer API, but I don't think
>> it is
>> considere public as the header cannot be found in /usr/include/mach
>
> In the man page for kevent it says that kevent timers are not
> supported ("EVFILT_TIMER This filter is currently unsupported."). I
> just assumed that the man page was correct and haven't made any tests.
> Are you sure kevent timers are implemented in Mac OS X? When it comes
> to Mach timers I wouldn't dare to use that in a commercial product
> since Apple seems to ask developers to keep away from Mach.
>
>> Anyway, that's the API used in CoreFoundation for CFTimer and
>> declared in
>> mk_timer.h (see XNU sources for details). But I wont go this way in a
>> shipping product.
>
> Agree... I will keep away from any private API:s.
>
> / PÃ¥hl
> -
I've used both the CF and NS timer apis in many different situations
without a hitch. They're fairly reliable. Perhaps you could explain
your "can't use a runloop" restriction -- e.g. if you are writing a
daemon or a kext, this is not the list you want to post to.
You might find if you refactor your design a bit, that it will take to
a runloop model quite well. In fact, most of the user space IOKit
async routines require that you use a runloop.
Also, the Mach APIs are not strictly private -- the headers are
publicly available. They are subject to change between releases, so if
you do start using them, you will need to stay on top of things --
check your binaries on pre-release OS seeds etc.
Joe K.
On Dec 4, 2008, at 6:17 AM, PÃ¥hl Melin wrote:> 2008/12/4 Jean-Daniel Dupas <devlists...>:
>> If you want to avoid Cocoa, Cocoa-dev is probably not the best
>> mailing list
>> to ask.
>> You will have more chance on darwin-dev.
>
> I don't want to avoid Cocoa, but I just haven't found any Cocoa class
> that supports timers without a run loop. But maybe I need to switch to
> darwin-dev.
>
>> What do you mean by "low-leve" ? What prevent you to use NS classes ?
>> Is this contraint preventing you to use CoreFoundation ? (which is
>> low-level IMHO).
>
> Nothing prevents me from using NS classes per se. I will use the
> timers in a C++ class and want to get a callback to a normal
> functionânot calling a selector on an Objective-C class that most NS
> classes would do. And since it's supposed to be the lowest level of my
> architecture I want it to be as efficient as possible.
>
> The only problem I have is that I will run the timers on threads
> without run loops so both NSTimer and CFRunLoopTimer (I didn't find
> any reference information about CFTimer on ADC) are impossible to use.
>
>> If you want lower level primitive, you can use kevent's timers, or
>> if you
>> want really low-level, there is a mach timer API, but I don't think
>> it is
>> considere public as the header cannot be found in /usr/include/mach
>
> In the man page for kevent it says that kevent timers are not
> supported ("EVFILT_TIMER This filter is currently unsupported."). I
> just assumed that the man page was correct and haven't made any tests.
> Are you sure kevent timers are implemented in Mac OS X? When it comes
> to Mach timers I wouldn't dare to use that in a commercial product
> since Apple seems to ask developers to keep away from Mach.
>
>> Anyway, that's the API used in CoreFoundation for CFTimer and
>> declared in
>> mk_timer.h (see XNU sources for details). But I wont go this way in a
>> shipping product.
>
> Agree... I will keep away from any private API:s.
> -
2008/12/4 Jean-Daniel Dupas <devlists...>:>
> Le 4 déc. 08 à 15:17, Påhl Melin a écrit :
>
>> 2008/12/4 Jean-Daniel Dupas <devlists...>:
>>>
>>> If you want to avoid Cocoa, Cocoa-dev is probably not the best mailing
>>> list
>>> to ask.
>>> You will have more chance on darwin-dev.
>>
>> I don't want to avoid Cocoa, but I just haven't found any Cocoa class
>> that supports timers without a run loop. But maybe I need to switch to
>> darwin-dev.
>>
>>> What do you mean by "low-leve" ? What prevent you to use NS classes ?
>>> Is this contraint preventing you to use CoreFoundation ? (which is
>>> low-level IMHO).
>>
>> Nothing prevents me from using NS classes per se. I will use the
>> timers in a C++ class and want to get a callback to a normal
>> functionânot calling a selector on an Objective-C class that most NS
>> classes would do. And since it's supposed to be the lowest level of my
>> architecture I want it to be as efficient as possible.
>>
>> The only problem I have is that I will run the timers on threads
>> without run loops so both NSTimer and CFRunLoopTimer (I didn't find
>> any reference information about CFTimer on ADC) are impossible to use.
>>
>
> Of course, CFTimer was a shortened form for CFRunLoopTimer.
>
> If you use timer, you need some primitive function that waits until one
> timer "trigger". I don't understand what is the difference between waiting
> using select, kevent,
> or any other primitive and waiting using CFRunLoopRun(). All threads have a
> runloop (or create one when needed), so I really don't understand what is
> the problem here.
The difference is that my threads will not have any run loops. They
will run all the time or sleep on a blocking primitive in my
framework. Only Cocoa threads automatically have a run loop (my
interpretation). I will run my threads using the pthread library
directly so no run loops are created.> For kevent, I'm surprised the doc say so, it look like it is implemented (at
> least in 10.4.11 and 10.5 XNU sources).
That's interesting. I will check it out. The man page is from april
14, 2000, so maybe Apple just forgot to update it.>
>
>>> If you want lower level primitive, you can use kevent's timers, or if you
>>> want really low-level, there is a mach timer API, but I don't think it is
>>> considere public as the header cannot be found in /usr/include/mach
>>
>> In the man page for kevent it says that kevent timers are not
>> supported ("EVFILT_TIMER This filter is currently unsupported."). I
>> just assumed that the man page was correct and haven't made any tests.
>> Are you sure kevent timers are implemented in Mac OS X? When it comes
>> to Mach timers I wouldn't dare to use that in a commercial product
>> since Apple seems to ask developers to keep away from Mach.
>>
>>> Anyway, that's the API used in CoreFoundation for CFTimer and declared in
>>> mk_timer.h (see XNU sources for details). But I wont go this way in a
>>> shipping product.
>>
>> Agree... I will keep away from any private API:s.
>>
>> / PÃ¥hl
>>
>
> -
2008/12/4 Joseph Kelly <joeman...>:> I've used both the CF and NS timer apis in many different situations without
> a hitch. They're fairly reliable. Perhaps you could explain your "can't use
> a runloop" restriction -- e.g. if you are writing a daemon or a kext, this
> is not the list you want to post to.
I'm not writing a daemon or a kext. I'm porting a framework that I've
designed and used on .Net before that will form the foundation of my
architecture for my future Mac OS applications (I'm new to Mac OS
programming). The framework is used for easy communication and
synchronization between threads, processes and computers (with the
same "syntax") and make it possible to design an application in small
modules that communicates via messages and it's straightforward to
start with the modules as threads in a single application and then
split into several processes on a computer or ever distribute certain
modules to other computers without changing much (or any) code at all.
But mainly it makes it easier to write efficient multithreaded
applications that "work".
I'm very happy with the messaging framework and would like to use it
on Mac OS X as well. Run loops are not compatible with this approach
since my threads need to run forever or block in my framework when
they are waiting for messages (the timers are used to generate timer
messages internally in the framework). The threads are not event
driven and will not return to the run loop.> You might find if you refactor your design a bit, that it will take to a
> runloop model quite well. In fact, most of the user space IOKit async
> routines require that you use a runloop.
I don't "want to" refactor my design. :-) To do that, I would have
give up the framework design completely. I'm generally happy with the
design just want to make a good port to Mac OS X.> Also, the Mach APIs are not strictly private -- the headers are publicly
> available. They are subject to change between releases, so if you do start
> using them, you will need to stay on top of things -- check your binaries on
> pre-release OS seeds etc.
Okay, thats great to know. But I suppose it's still begging for
trouble, if you can avoid it.> Joe K. -
Le 4 déc. 08 à 15:50, Påhl Melin a écrit :> 2008/12/4 Jean-Daniel Dupas <devlists...>:
>>
>> Le 4 déc. 08 à 15:17, Påhl Melin a écrit :
>>
>>> 2008/12/4 Jean-Daniel Dupas <devlists...>:
>>>>
>>>> If you want to avoid Cocoa, Cocoa-dev is probably not the best
>>>> mailing
>>>> list
>>>> to ask.
>>>> You will have more chance on darwin-dev.
>>>
>>> I don't want to avoid Cocoa, but I just haven't found any Cocoa
>>> class
>>> that supports timers without a run loop. But maybe I need to
>>> switch to
>>> darwin-dev.
>>>
>>>> What do you mean by "low-leve" ? What prevent you to use NS
>>>> classes ?
>>>> Is this contraint preventing you to use CoreFoundation ? (which is
>>>> low-level IMHO).
>>>
>>> Nothing prevents me from using NS classes per se. I will use the
>>> timers in a C++ class and want to get a callback to a normal
>>> functionânot calling a selector on an Objective-C class that most NS
>>> classes would do. And since it's supposed to be the lowest level
>>> of my
>>> architecture I want it to be as efficient as possible.
>>>
>>> The only problem I have is that I will run the timers on threads
>>> without run loops so both NSTimer and CFRunLoopTimer (I didn't find
>>> any reference information about CFTimer on ADC) are impossible to
>>> use.
>>>
>>
>> Of course, CFTimer was a shortened form for CFRunLoopTimer.
>>
>> If you use timer, you need some primitive function that waits until
>> one
>> timer "trigger". I don't understand what is the difference between
>> waiting
>> using select, kevent,
>> or any other primitive and waiting using CFRunLoopRun(). All
>> threads have a
>> runloop (or create one when needed), so I really don't understand
>> what is
>> the problem here.
>
> The difference is that my threads will not have any run loops. They
> will run all the time or sleep on a blocking primitive in my
> framework. Only Cocoa threads automatically have a run loop (my
> interpretation). I will run my threads using the pthread library
> directly so no run loops are created.
My understanding is that ALL threads have a runloop (from the
CFRunLoop doc):
«There is exactly one run loop per thread. You neither create nor
destroy a threadâs run loop. Core Foundation automatically creates it
for you as needed. »
As CoreFoundation is not part of Cocoa, I doubt that only Cocoa thread
can have a CFRunLoop. (In fact, I do not doubt, i'm pretty sure
CoreFoundation is based on pthread and do not use Cocoa at all).
I did tool that do not use obj-c at all and use pthread and CFRunLoop
to managed networks events (using CFSocket) and it works just as it
should.>> For kevent, I'm surprised the doc say so, it look like it is
>> implemented (at
>> least in 10.4.11 and 10.5 XNU sources).
>
> That's interesting. I will check it out. The man page is from april
> 14, 2000, so maybe Apple just forgot to update it.
>
>>
>>
>>>> If you want lower level primitive, you can use kevent's timers,
>>>> or if you
>>>> want really low-level, there is a mach timer API, but I don't
>>>> think it is
>>>> considere public as the header cannot be found in /usr/include/mach
>>>
>>> In the man page for kevent it says that kevent timers are not
>>> supported ("EVFILT_TIMER This filter is currently unsupported."). I
>>> just assumed that the man page was correct and haven't made any
>>> tests.
>>> Are you sure kevent timers are implemented in Mac OS X? When it
>>> comes
>>> to Mach timers I wouldn't dare to use that in a commercial product
>>> since Apple seems to ask developers to keep away from Mach.
>>>
>>>> Anyway, that's the API used in CoreFoundation for CFTimer and
>>>> declared in
>>>> mk_timer.h (see XNU sources for details). But I wont go this way
>>>> in a
>>>> shipping product.
>>>
>>> Agree... I will keep away from any private API:s.
>>>
>>> / PÃ¥hl
>>>
>> -
If I were trying to generate an asynchronous timer event in C I'd
probably just run a thread in a tight loop calling poll (man 2 poll
for details) each time round with a timeout equal to your timer
interval and no other events. And when the poll returns do whatever
processing you need on your timer.
Will that not work for you?
Otherwise your question seems to be "How can I use any of the high
level Mac OS X timer facilities without using the high level Mac OS X
timer facilities?" for which there is, of course, no answer.
On 4 Dec 2008, at 15:14, PÃ¥hl Melin wrote:> 2008/12/4 Joseph Kelly <joeman...>:
>> I've used both the CF and NS timer apis in many different
>> situations without
>> a hitch. They're fairly reliable. Perhaps you could explain your
>> "can't use
>> a runloop" restriction -- e.g. if you are writing a daemon or a
>> kext, this
>> is not the list you want to post to.
>
> I'm not writing a daemon or a kext. I'm porting a framework that I've
> designed and used on .Net before that will form the foundation of my
> architecture for my future Mac OS applications (I'm new to Mac OS
> programming). The framework is used for easy communication and
> synchronization between threads, processes and computers (with the
> same "syntax") and make it possible to design an application in small
> modules that communicates via messages and it's straightforward to
> start with the modules as threads in a single application and then
> split into several processes on a computer or ever distribute certain
> modules to other computers without changing much (or any) code at all.
> But mainly it makes it easier to write efficient multithreaded
> applications that "work".
>
> I'm very happy with the messaging framework and would like to use it
> on Mac OS X as well. Run loops are not compatible with this approach
> since my threads need to run forever or block in my framework when
> they are waiting for messages (the timers are used to generate timer
> messages internally in the framework). The threads are not event
> driven and will not return to the run loop.
>
>> You might find if you refactor your design a bit, that it will take
>> to a
>> runloop model quite well. In fact, most of the user space IOKit async
>> routines require that you use a runloop.
>
> I don't "want to" refactor my design. :-) To do that, I would have
> give up the framework design completely. I'm generally happy with the
> design just want to make a good port to Mac OS X.
>
>> Also, the Mach APIs are not strictly private -- the headers are
>> publicly
>> available. They are subject to change between releases, so if you
>> do start
>> using them, you will need to stay on top of things -- check your
>> binaries on
>> pre-release OS seeds etc.
>
> Okay, thats great to know. But I suppose it's still begging for
> trouble, if you can avoid it.
>
>> Joe K. -
I don't mean to sound patronizing, but unless I have missed some fundamental
premise, didn't you just re-invent DO? Maybe the right way to port this
framework is to make your API a thin wrapper on top of Obj-C messages, and
your set up a wrapper on top of DO setup. Just a thought.
- Dave.S
On Thu, Dec 4, 2008 at 8:41 AM, Jeremy Pereira <adc...> wrote:> If I were trying to generate an asynchronous timer event in C I'd probably
> just run a thread in a tight loop calling poll (man 2 poll for details) each
> time round with a timeout equal to your timer interval and no other events.
> And when the poll returns do whatever processing you need on your timer.
>
> Will that not work for you?
>
> Otherwise your question seems to be "How can I use any of the high level
> Mac OS X timer facilities without using the high level Mac OS X timer
> facilities?" for which there is, of course, no answer.
>
> On 4 Dec 2008, at 15:14, PÃ¥hl Melin wrote:
>
> 2008/12/4 Joseph Kelly <joeman...>:
>>
>>> I've used both the CF and NS timer apis in many different situations
>>> without
>>> a hitch. They're fairly reliable. Perhaps you could explain your "can't
>>> use
>>> a runloop" restriction -- e.g. if you are writing a daemon or a kext,
>>> this
>>> is not the list you want to post to.
>>>
>>
>> I'm not writing a daemon or a kext. I'm porting a framework that I've
>> designed and used on .Net before that will form the foundation of my
>> architecture for my future Mac OS applications (I'm new to Mac OS
>> programming). The framework is used for easy communication and
>> synchronization between threads, processes and computers (with the
>> same "syntax") and make it possible to design an application in small
>> modules that communicates via messages and it's straightforward to
>> start with the modules as threads in a single application and then
>> split into several processes on a computer or ever distribute certain
>> modules to other computers without changing much (or any) code at all.
>> But mainly it makes it easier to write efficient multithreaded
>> applications that "work".
>>
>> I'm very happy with the messaging framework and would like to use it
>> on Mac OS X as well. Run loops are not compatible with this approach
>> since my threads need to run forever or block in my framework when
>> they are waiting for messages (the timers are used to generate timer
>> messages internally in the framework). The threads are not event
>> driven and will not return to the run loop.
>>
>> You might find if you refactor your design a bit, that it will take to a
>>> runloop model quite well. In fact, most of the user space IOKit async
>>> routines require that you use a runloop.
>>>
>>
>> I don't "want to" refactor my design. :-) To do that, I would have
>> give up the framework design completely. I'm generally happy with the
>> design just want to make a good port to Mac OS X.
>>
>> Also, the Mach APIs are not strictly private -- the headers are publicly
>>> available. They are subject to change between releases, so if you do
>>> start
>>> using them, you will need to stay on top of things -- check your binaries
>>> on
>>> pre-release OS seeds etc.
>>>
>>
>> Okay, thats great to know. But I suppose it's still begging for
>> trouble, if you can avoid it.
>>
>> Joe K.
>>>
>>
>
--
http://go/OnlyCheckEmailTwiceADay - join the movement -
The question itself does not make a lot of sense for me. A timer API is
tightly bound to the underlying framework that is idling your thread.
If the idling API is CFRunLoopRun(), you'd use CFTimers, if your idling API
is select() or kevent(), you'd use their timeout parameters.
So, for what you seem to say, it's your framework responsibility to provide
some "asynchronous timer API". If it does not, your only choice is to
simulate the timer using other means:
- the easy one: one thread that sleeps() for each timer then messages back
to your threads
- a more complex one is to use a dedicated thread that will effectively run
a CFRunLoop and bridge your timers over CFTimers.
- you could imagine using signal() +SIGALRM bug using Unix signals here is
really not something you should try to use except if you really know what
you are doing.
--
Julien
On Thu, Dec 4, 2008 at 4:14 PM, PÃÂ¥hl Melin <listor.pm...> wrote:> 2008/12/4 Joseph Kelly <joeman...>:
>> I've used both the CF and NS timer apis in many different situations
> without
>> a hitch. They're fairly reliable. Perhaps you could explain your "can't
> use
>> a runloop" restriction -- e.g. if you are writing a daemon or a kext,
> this
>> is not the list you want to post to.
>
> I'm not writing a daemon or a kext. I'm porting a framework that I've
> designed and used on .Net before that will form the foundation of my
> architecture for my future Mac OS applications (I'm new to Mac OS
> programming). The framework is used for easy communication and
> synchronization between threads, processes and computers (with the
> same "syntax") and make it possible to design an application in small
> modules that communicates via messages and it's straightforward to
> start with the modules as threads in a single application and then
> split into several processes on a computer or ever distribute certain
> modules to other computers without changing much (or any) code at all.
> But mainly it makes it easier to write efficient multithreaded
> applications that "work".
>
> I'm very happy with the messaging framework and would like to use it
> on Mac OS X as well. Run loops are not compatible with this approach
> since my threads need to run forever or block in my framework when
> they are waiting for messages (the timers are used to generate timer
> messages internally in the framework). The threads are not event
> driven and will not return to the run loop.
>
>> You might find if you refactor your design a bit, that it will take to a
>> runloop model quite well. In fact, most of the user space IOKit async
>> routines require that you use a runloop.
>
> I don't "want to" refactor my design. :-) To do that, I would have
> give up the framework design completely. I'm generally happy with the
> design just want to make a good port to Mac OS X.
>
>> Also, the Mach APIs are not strictly private -- the headers are publicly
>> available. They are subject to change between releases, so if you do
> start
>> using them, you will need to stay on top of things -- check your binaries
> on
>> pre-release OS seeds etc.
>
> Okay, thats great to know. But I suppose it's still begging for
> trouble, if you can avoid it.
>
>> Joe K.
> -
On Dec 4, 2008, at 7:14 AM, PÃ¥hl Melin wrote:>
> I'm very happy with the messaging framework and would like to use it
> on Mac OS X as well. Run loops are not compatible with this approach
> since my threads need to run forever or block in my framework when
> they are waiting for messages (the timers are used to generate timer
> messages internally in the framework).
To give you some perspective, that's exactly what Runloops do. They
block a thread indefinitely until a "message" comes in, at which point
the thread unblocks and begins executing some kind of callback
routine. When the callback returns, the thread blocks again until the
next message comes in. Runloops are simply an abstraction that
associates an arbitrary thread with a set (or sets) of triggers which
cause the thread to unblock and do something.
So for instance, to give you a top level overview of how this might
work -- this is a rough C example, but could be adapted to an OOP model:
CFRunLoopRef gWorkerThreadRLoop = NULL; // this could be a global
variable or a member variable of a C++ or ObjC object.
main(...)
{
SpawnAThread(MyThreadRoutine); // you could use pthreads, or
NSThread, or even Boost threads.
while(gWorkerThreadRLoop == NULL); // prbly add a timeout / sleep here.
// init some other stuff
... Run the Main Thread's Runloop...
// Something causes us to wake up, so lets forward a message to the
worker thread:
TriggerAMessage(gWorkerThreadRLoop, msg1);
TriggerAMessage(gWorkerThreadRLoop, msg2);
...
// time to quit
CFRunLoopStop(gWorkerThreadRLoop)
}
MyThreadRoutine(...)
{
gWorkerThreadRLoop = CFRunLoopGetCurrent(); // this will
automatically/implicitly create the runloop associated w/ this thread.
... add the timer and other sources...
CFRunLoopRun();
... remove my sources / timers...
gWorkerThreadRLoop = NULL;
}
MsgDispatcher(incomingMsg) // this gets called on the worker thread in
response to TriggerAMessage
{
// Dispatch the incomingMsg
}
If this looks suitable, I can give you more details about how to
implement.
Joe K. -
On Thu, Dec 4, 2008 at 8:00 AM, PÃÂ¥hl Melin <listor.pm...> wrote:> Yes, I could set up a new thread, handling a list of usleep()
> intervals between the actual timer events but it would be very hard to
> make a reliable, drift-free timer service, handling lots of timer
> events and it would take quite some time to develop a fully functional
> and reliable version. I really hope I don't have to...
You know, if you set up a new thread, then run an NSRunLoop on it and
schedule timers on that, then you will get a reliable, drift-free
timer service, handling lots of timer events, fully functional and
reliable, with approximately zero work on your part.
If you can use a separate thread, you can use a runloop. I don't see
why you're trying to avoid them, perhaps you're unaware of this fact?
Mike -
2008/12/4 Julien Jalon <jjalon...>:> The question itself does not make a lot of sense for me. A timer API is
> tightly bound to the underlying framework that is idling your thread.
> If the idling API is CFRunLoopRun(), you'd use CFTimers, if your idling API
> is select() or kevent(), you'd use their timeout parameters.
> So, for what you seem to say, it's your framework responsibility to provide
> some "asynchronous timer API". If it does not, your only choice is to
> simulate the timer using other means:
> - the easy one: one thread that sleeps() for each timer then messages back
> to your threads
> - a more complex one is to use a dedicated thread that will effectively run
> a CFRunLoop and bridge your timers over CFTimers.
> - you could imagine using signal() +SIGALRM bug using Unix signals here is
> really not something you should try to use except if you really know what
> you are doing.
The reason I asked for a simple Timer API without using a run loop is
because I'm converting my framework from Dotnet where such a Timer API
exists and makes it dead simple to setup multiple timers without
blocking or setting up a dedicated thread in each process for just
handling the timers. In C++/CLI using Dotnet you just specify:
Timer^ myTimer = gcnew Timer(gcnew TimerCallback(&TimerFunction),
nullptr, 5000, 500);
...to have the TimerFunction() function be called twice per second
after 5 seconds (time in millisecond). Nothing else â you don't need
to idle your thread at all. Dotnet handles everything by itself.
Setting up multiple timers is just repeating the line of code above.
(gcnew is just new on the garbage collect heap and the carret '^' is
just a pointer/handle to the garbage collect heap if you don't know
Microsoft C++/CLI)
Since it's so easy in Dotnet and Cocoa (plus the other API:s in Mac OS
X) is even more mature, I just assumed it would be just as easy in Mac
OS X. But it seems I was wrong. Of course, if you happen to already
use an event-driven design using run loops in Cocoa/Core Foundation
it's very easy here as well. But since I'm not...
Thanks everyone for giving me advice on setting up a separate thread
with a run loop (of any kind) to handle timers. It seem like the best
solution to make my own Timer API with a separate thread to simulate
the Dotnet Timer API. I just wish didn't have to. Maybe a feature
request for future Mac OS X releases...
/ PÃ¥hl -
2008/12/4 David Springer <dspringer...>:> I don't mean to sound patronizing, but unless I have missed some fundamental
> premise, didn't you just re-invent DO? Maybe the right way to port this
> framework is to make your API a thin wrapper on top of Obj-C messages, and
> your set up a wrapper on top of DO setup. Just a thought.
No problem. It's a valid question. When I first designed the framework
on Dotnet, I did it partly because I wasn't satisfied with the
Remoting framework (which is Dotnet's version of Distributed Objects).
In the end I suppose it's mainly a matter of taste, but I much prefer
the flexibility you get with message passing framework, rather than a
distributed object framework. In my opinion it's more encouraging to
use multithreading if it's easy to do ad-hoc messaging between threads
and processes without having to specify a new class for each
communication. And my messaging framework also includes some other
nice features I wouldn't get with DO.
/ PÃ¥hl -
Le 5 déc. 08 à 13:52, Påhl Melin a écrit :> 2008/12/4 Julien Jalon <jjalon...>:
>> The question itself does not make a lot of sense for me. A timer
>> API is
>> tightly bound to the underlying framework that is idling your thread.
>> If the idling API is CFRunLoopRun(), you'd use CFTimers, if your
>> idling API
>> is select() or kevent(), you'd use their timeout parameters.
>> So, for what you seem to say, it's your framework responsibility to
>> provide
>> some "asynchronous timer API". If it does not, your only choice is to
>> simulate the timer using other means:
>> - the easy one: one thread that sleeps() for each timer then
>> messages back
>> to your threads
>> - a more complex one is to use a dedicated thread that will
>> effectively run
>> a CFRunLoop and bridge your timers over CFTimers.
>> - you could imagine using signal() +SIGALRM bug using Unix signals
>> here is
>> really not something you should try to use except if you really
>> know what
>> you are doing.
>
> The reason I asked for a simple Timer API without using a run loop is
> because I'm converting my framework from Dotnet where such a Timer API
> exists and makes it dead simple to setup multiple timers without
> blocking or setting up a dedicated thread in each process for just
> handling the timers. In C++/CLI using Dotnet you just specify:
>
> Timer^ myTimer = gcnew Timer(gcnew TimerCallback(&TimerFunction),
> nullptr, 5000, 500);
>
> ...to have the TimerFunction() function be called twice per second
> after 5 seconds (time in millisecond). Nothing else â you don't need
> to idle your thread at all. Dotnet handles everything by itself.
> Setting up multiple timers is just repeating the line of code above.
> (gcnew is just new on the garbage collect heap and the carret '^' is
> just a pointer/handle to the garbage collect heap if you don't know
> Microsoft C++/CLI)
>
> Since it's so easy in Dotnet and Cocoa (plus the other API:s in Mac OS
> X) is even more mature, I just assumed it would be just as easy in Mac
> OS X. But it seems I was wrong. Of course, if you happen to already
> use an event-driven design using run loops in Cocoa/Core Foundation
> it's very easy here as well. But since I'm not...
>
> Thanks everyone for giving me advice on setting up a separate thread
> with a run loop (of any kind) to handle timers. It seem like the best
> solution to make my own Timer API with a separate thread to simulate
> the Dotnet Timer API. I just wish didn't have to. Maybe a feature
> request for future Mac OS X releases...
The dotnet timer is useless for a lots of cases for one reason: "The
method does not execute on the thread that created the timer"
It uses a theadpool setup by the framework in background.
I really prefere the OS X approach that let you do something similar
in 5 lines of code, but is more flexible, as it also allow you to
execute timer on a predefined thread.
Now, you can request a wrapper API that create it's own thread, and
call a callback function on a random thread when it triggers, but I
doubt they will include it in Cocoa. -
2008/12/4 Jean-Daniel Dupas <devlists...>:> My understanding is that ALL threads have a runloop (from the CFRunLoop
> doc):
>
> «There is exactly one run loop per thread. You neither create nor destroy a
> thread's run loop. Core Foundation automatically creates it for you as
> needed. »
>
> As CoreFoundation is not part of Cocoa, I doubt that only Cocoa thread can
> have a CFRunLoop. (In fact, I do not doubt, i'm pretty sure CoreFoundation
> is based on pthread and do not use Cocoa at all).
>
> I did tool that do not use obj-c at all and use pthread and CFRunLoop to
> managed networks events (using CFSocket) and it works just as it should.
After skimming the "Threading Programming Guide",I realize you are
right about the run loops. All threads have a run loop, including
pthread-created ones. But you have to configure and start the run loop
for all threads other than the main thread. I'm learning new stuff all
the time... :-)
/ PÃ¥hl -
2008/12/5 Jean-Daniel Dupas <devlists...>:> The dotnet timer is useless for a lots of cases for one reason: "The method
> does not execute on the thread that created the timer"
> It uses a theadpool setup by the framework in background.
In my case, I have no need at all, to run the callback from any
particular thread. The callback function is handling a shared resource
and is thus reentrant and uses a mutex lock to protect the resource. A
quite common case â but of course, sometimes it's nice not caring
about synchronization.> I really prefere the OS X approach that let you do something similar in 5
> lines of code, but is more flexible, as it also allow you to execute timer
> on a predefined thread.
A matter of taste â for both approaches. Sometimes one a approach is
better than the other and sometimes vice versa.> Now, you can request a wrapper API that create it's own thread, and call a
> callback function on a random thread when it triggers, but I doubt they will
> include it in Cocoa.
I doubt it too...
/ PÃ¥hl -
2008/12/5 Benjamin Stiglitz <stig...>:>> I need to use timers in a low level library where I need to specify
>> asynchronous callbacks to a timer function. I will not have any run
>> loop so I cannot use NSTimer. Are there any low level timer API to use
>> instead? I haven't found anything useful (yet) on google nor ADC. I
>> assume there must exist some Mach or BSD level API:s that can be used?
>
> alarm(3) or setitimer(2).
setitimer(2) could be used if I calculate the relative difference
between multiple timer settings and resetting to the next interval
after each signal. Some extra work but doable. When using multiple
timers the alarms could possible start to drift I suppose.
But I got the impression from Jean-Daniel Dupas, that kevent() with
the timer filter EVFILT_TIMER is implemented even though the man page
of kqueue(2) says "EVFILT_TIMER This filter is currently unsupported."
Do you know from which OS X version kevent() timers are supported? Or
if they are officially supported at all?
...and how do you setup multiple timer events? In the kqueue(2) man
page for OpenBSD 4.3 it says: "EVFILT_TIMER Establishes an arbitrary
timer identified by ident..." Is the timer identifier something you
(as in: me the programmer) selects randomly for the struct kevent{} 's
ident member field or do I generate the id with some library call
beforehand?
/ PÃ¥hl -
Le 5 déc. 08 à 16:00, Påhl Melin a écrit :> 2008/12/5 Benjamin Stiglitz <stig...>:
>>> I need to use timers in a low level library where I need to specify
>>> asynchronous callbacks to a timer function. I will not have any run
>>> loop so I cannot use NSTimer. Are there any low level timer API to
>>> use
>>> instead? I haven't found anything useful (yet) on google nor ADC. I
>>> assume there must exist some Mach or BSD level API:s that can be
>>> used?
>>
>> alarm(3) or setitimer(2).
>
> setitimer(2) could be used if I calculate the relative difference
> between multiple timer settings and resetting to the next interval
> after each signal. Some extra work but doable. When using multiple
> timers the alarms could possible start to drift I suppose.
>
> But I got the impression from Jean-Daniel Dupas, that kevent() with
> the timer filter EVFILT_TIMER is implemented even though the man page
> of kqueue(2) says "EVFILT_TIMER This filter is currently unsupported."
>
> Do you know from which OS X version kevent() timers are supported? Or
> if they are officially supported at all?
>
They are commented out in 10.3.9 sources, and implemented in 10.4.0
sources.
I guess than man page has not been updated at this time.> ...and how do you setup multiple timer events? In the kqueue(2) man
> page for OpenBSD 4.3 it says: "EVFILT_TIMER Establishes an arbitrary
> timer identified by ident..." Is the timer identifier something you
> (as in: me the programmer) selects randomly for the struct kevent{} 's
> ident member field or do I generate the id with some library call
> beforehand? -
On Fri, Dec 5, 2008 at 7:52 AM, PÃÂ¥hl Melin <listor.pm...> wrote:> The reason I asked for a simple Timer API without using a run loop is
> because I'm converting my framework from Dotnet where such a Timer API
> exists and makes it dead simple to setup multiple timers without
> blocking or setting up a dedicated thread in each process for just
> handling the timers. In C++/CLI using Dotnet you just specify:
>
> Timer^ myTimer = gcnew Timer(gcnew TimerCallback(&TimerFunction),
> nullptr, 5000, 500);
>
> ...to have the TimerFunction() function be called twice per second
> after 5 seconds (time in millisecond). Nothing else ââ¬â you don't need
> to idle your thread at all. Dotnet handles everything by itself.
> Setting up multiple timers is just repeating the line of code above.
> (gcnew is just new on the garbage collect heap and the carret '^' is
> just a pointer/handle to the garbage collect heap if you don't know
> Microsoft C++/CLI)
If you use a CFRunLoopTimer then your code will be roughly as simple
as that. All you need to do is spawn off a thread at the beginning of
your program and have it sit inside CFRunLoopRun. Store a reference to
its runloop somewhere, and then install timers on it. CFRunLoop is
thread safe, so you can easily and directly create timers and schedule
them on your timer thread's runloop without any extra protection.
Of course you will have to write some setup code to create that timer
thread. But this will be perhaps ten lines of code.
And of course your timer callbacks will end up running in a separate
thread, which mean you'll have to worry about thread safety. But given
the API above, I imagine something similar must be happening there, so
that won't be a big change.
Mike -
On Dec 5, 2008, at 7:52 AM, PÃ¥hl Melin wrote:> ...to have the TimerFunction() function be called twice per second
> after 5 seconds (time in millisecond). Nothing else â you don't need
> to idle your thread at all. Dotnet handles everything by itself.
> Setting up multiple timers is just repeating the line of code above.
> (gcnew is just new on the garbage collect heap and the carret '^' is
> just a pointer/handle to the garbage collect heap if you don't know
> Microsoft C++/CLI)
>
> Since it's so easy in Dotnet and Cocoa (plus the other API:s in Mac OS
> X) is even more mature, I just assumed it would be just as easy in Mac
> OS X. But it seems I was wrong.
No, you were right. Doing such a thing is quite easy in Cocoa. It's
just like in .NET, a single call to a NSTimer class method, that
accepts arguments giving the interval, callback object, and the
message to send to that object when the timer fires.> Of course, if you happen to already
> use an event-driven design using run loops in Cocoa/Core Foundation
> it's very easy here as well. But since I'm not...
So why aren't you? If you choose to make things difficult for
yourself, they will be. Why do you find that surprising?> Thanks everyone for giving me advice on setting up a separate thread
> with a run loop (of any kind) to handle timers. It seem like the best
> solution to make my own Timer API with a separate thread to simulate
> the Dotnet Timer API. I just wish didn't have to.
You're trying to act as if Cocoa is "supposed" to work like .NET, but
no one is "making" you do that. You're asking for trouble, and getting
what you asked for.
You'd have far, far less trouble programming for the Mac if you'd
simply learn how Cocoa works, instead of trying to reinvent .NET in
Objective-C. When in Rome, do as the Romans do.
sherm-- -
2008/12/5 Jean-Daniel Dupas <devlists...>:>
> Le 5 déc. 08 à 16:00, Påhl Melin a écrit :
>
>> 2008/12/5 Benjamin Stiglitz <stig...>:
>>>>
>>>> I need to use timers in a low level library where I need to specify
>>>> asynchronous callbacks to a timer function. I will not have any run
>>>> loop so I cannot use NSTimer. Are there any low level timer API to use
>>>> instead? I haven't found anything useful (yet) on google nor ADC. I
>>>> assume there must exist some Mach or BSD level API:s that can be used?
>>>
>>> alarm(3) or setitimer(2).
>>
>> setitimer(2) could be used if I calculate the relative difference
>> between multiple timer settings and resetting to the next interval
>> after each signal. Some extra work but doable. When using multiple
>> timers the alarms could possible start to drift I suppose.
>>
>> But I got the impression from Jean-Daniel Dupas, that kevent() with
>> the timer filter EVFILT_TIMER is implemented even though the man page
>> of kqueue(2) says "EVFILT_TIMER This filter is currently unsupported."
>>
>> Do you know from which OS X version kevent() timers are supported? Or
>> if they are officially supported at all?
>>
>
> They are commented out in 10.3.9 sources, and implemented in 10.4.0 sources.
> I guess than man page has not been updated at this time.
Ah, great, thanks. Then it feels safe to use kevent:s . I'm
considering to use Leopard as the minimum requirement anyway.
/ PÃ¥hl -
2008/12/5 Joseph Kelly <joeman...>:> From everything you've said, PÃ¥hl, you can very easily implement it using a
> combination of Cocoa and Core Foundation. I posted a response yesterday
> which you might want to look at.
Thanks Joseph. I looked at your source more closely and I think I get
the idea how to use Core Foundation to run the timers in a separate
thread with a CFRunLoop. It looks quite straightforward. I really
appreciate the sample code. It's makes it so much easier than just
reading the reference material on ADC.
It's come down to a choice between kernel queue's kevent() timers and
CFRunLoopTimers on a separate thread. I'll have to do some test this
weekend...
/ PÃ¥hl -
2008/12/5 Sherm Pendley <sherm.pendley...>:> On Dec 5, 2008, at 7:52 AM, PÃ¥hl Melin wrote:
>
>> ...to have the TimerFunction() function be called twice per second
>> after 5 seconds (time in millisecond). Nothing else â you don't need
>> to idle your thread at all. Dotnet handles everything by itself.
>> Setting up multiple timers is just repeating the line of code above.
>> (gcnew is just new on the garbage collect heap and the carret '^' is
>> just a pointer/handle to the garbage collect heap if you don't know
>> Microsoft C++/CLI)
>>
>> Since it's so easy in Dotnet and Cocoa (plus the other API:s in Mac OS
>> X) is even more mature, I just assumed it would be just as easy in Mac
>> OS X. But it seems I was wrong.
>
> No, you were right. Doing such a thing is quite easy in Cocoa. It's just
> like in .NET, a single call to a NSTimer class method, that accepts
> arguments giving the interval, callback object, and the message to send to
> that object when the timer fires.
>
>> Of course, if you happen to already
>> use an event-driven design using run loops in Cocoa/Core Foundation
>> it's very easy here as well. But since I'm not...
>
> So why aren't you? If you choose to make things difficult for yourself, they
> will be. Why do you find that surprising?
Simply because I didn't know I was making things difficult for me.>> Thanks everyone for giving me advice on setting up a separate thread
>> with a run loop (of any kind) to handle timers. It seem like the best
>> solution to make my own Timer API with a separate thread to simulate
>> the Dotnet Timer API. I just wish didn't have to.
>
> You're trying to act as if Cocoa is "supposed" to work like .NET, but no one
> is "making" you do that. You're asking for trouble, and getting what you
> asked for.
>
> You'd have far, far less trouble programming for the Mac if you'd simply
> learn how Cocoa works, instead of trying to reinvent .NET in Objective-C.
> When in Rome, do as the Romans do.
That's why I asked in the first place. I didn't know how Cocoa works
in regards to timers. And so far, I've done most of my Mac programming
in BSD Unix where run loops are not used at all so it's not quite
super obvious how to implement multiple timer handling in Mac OS X. At
least I didn't think so.
/ PÃ¥hl -
On Dec 5, 2008, at 3:16 PM, PÃ¥hl Melin wrote:> 2008/12/5 Sherm Pendley <sherm.pendley...>:
>>
>> You'd have far, far less trouble programming for the Mac if you'd
>> simply
>> learn how Cocoa works, instead of trying to reinvent .NET in
>> Objective-C.
>> When in Rome, do as the Romans do.
>
> That's why I asked in the first place. I didn't know how Cocoa works
> in regards to timers.
I understand that - and it's a good point. But consider how you asked
the question. If you don't know how Cocoa works, how is it that you've
already decided that you shouldn't use a run loop? That's putting the
cart in front of the horse, IMHO. The fact that you don't use a run
loop to build timers with some other framework doesn't imply that you
shouldn't do so when you're using Cocoa.
Unless I've missed something, you have a classic A/B situation. You
want to do task A - fire a timer event every half second, starting
five seconds from now. And based on your experience with .Net and BSD,
you've decided that method B - threading without run loops - is how
you want to do that, so you're asking for help with method B. The
problem is that the method B isn't the best match for Cocoa's way of
doing things, and actually makes task A far more difficult than it
normally would be. You need to take a step further back, and find out
how Cocoa does task A.
So, how to do task A the "Cocoa way?" Here's a simple example:
- (void)startTimer {
NSTimer * t = [NSTimer scheduledTimerWithTimeInterval: 4.5
target: self
selector: @selector(delayTimerFired:)
userInfo: nil
repeats: NO
];
}
- (void)delayTimerFired:(NSTimer *)theTimer {
// Create interval timer
NSTimer * t = [NSTimer scheduledTimerWithTimeInterval: 0.5
target: self
selector: @selector(intervalTimerFired:)
userInfo: nil
repeats: YES
];
}
- (void)intervalTimerFired:(NSTimer *)theTimer {
// do stuff every half second
}
If you want to invalidate the timer at some future point, you could do
so directly by storing a reference to it in an instance variable. Or,
you could check for some condition in -intervalTimerFired:, and send
[theTimer invalidate] if needed.
sherm-- -
2008/12/5 Sherm Pendley <sherm.pendley...>:> On Dec 5, 2008, at 3:16 PM, PÃ¥hl Melin wrote:
>
>> 2008/12/5 Sherm Pendley <sherm.pendley...>:
>>>
>>> You'd have far, far less trouble programming for the Mac if you'd simply
>>> learn how Cocoa works, instead of trying to reinvent .NET in Objective-C.
>>> When in Rome, do as the Romans do.
>>
>> That's why I asked in the first place. I didn't know how Cocoa works
>> in regards to timers.
>
> I understand that - and it's a good point. But consider how you asked the
> question. If you don't know how Cocoa works, how is it that you've already
> decided that you shouldn't use a run loop? That's putting the cart in front
> of the horse, IMHO. The fact that you don't use a run loop to build timers
> with some other framework doesn't imply that you shouldn't do so when you're
> using Cocoa.
I didn't really decide I shouldn't use a run loop for the timers. I am
porting a library from another platform and just wanted a quick answer
if I could get a similar timer API behavior in either Cocoa, Core
Foundation or BSD Unix (with a preference on low-level for
efficiency), as I was already using. It would save me time and make
the resulting code simpler and probably more robust (since I'm not an
Cocoa/CF expert).> Unless I've missed something, you have a classic A/B situation. You want to
> do task A - fire a timer event every half second, starting five seconds from
> now. And based on your experience with .Net and BSD, you've decided that
> method B - threading without run loops - is how you want to do that, so
> you're asking for help with method B. The problem is that the method B isn't
> the best match for Cocoa's way of doing things, and actually makes task A
> far more difficult than it normally would be. You need to take a step
> further back, and find out how Cocoa does task A.
>
> So, how to do task A the "Cocoa way?" Here's a simple example:
>
> - (void)startTimer {
> NSTimer * t = [NSTimer scheduledTimerWithTimeInterval: 4.5
> target: self
> selector: @selector(delayTimerFired:)
> userInfo: nil
> repeats: NO
> ];
> }
>
> - (void)delayTimerFired:(NSTimer *)theTimer {
> // Create interval timer
> NSTimer * t = [NSTimer scheduledTimerWithTimeInterval: 0.5
> target: self
> selector: @selector(intervalTimerFired:)
> userInfo: nil
> repeats: YES
> ];
> }
>
> - (void)intervalTimerFired:(NSTimer *)theTimer {
> // do stuff every half second
> }
>
> If you want to invalidate the timer at some future point, you could do so
> directly by storing a reference to it in an instance variable. Or, you could
> check for some condition in -intervalTimerFired:, and send [theTimer
> invalidate] if needed.
Thanks for the explanation on Cocoa timers.
/ PÃ¥hl -
On Dec 5, 2008, at 3:22 PM, PÃ¥hl Melin wrote:> I didn't really decide I shouldn't use a run loop for the timers. I am
> porting a library from another platform and just wanted a quick answer
> if I could get a similar timer API behavior in either Cocoa, Core
> Foundation or BSD Unix (with a preference on low-level for
> efficiency), as I was already using. It would save me time and make
> the resulting code simpler and probably more robust (since I'm not an
> Cocoa/CF expert).
In the spirit of helping to ask better questions...
I think the key piece of information that you left out in your
original question was the API you were using on .Net, and the behavior
you got - that your timer was called on a separate thread, _not_ the
thread that installed the timer. Given that information, it would be
easy to direct you at simply creating a separate thread and using
either NSTimer or CFRunLoopTimer to install your timers, which would
be called on the separate thread, exactly as on .Net.
-eric -
Le 6 déc. 08 à 00:22, Påhl Melin a écrit :> 2008/12/5 Sherm Pendley <sherm.pendley...>:
>> On Dec 5, 2008, at 3:16 PM, PÃ¥hl Melin wrote:
>>
>>> 2008/12/5 Sherm Pendley <sherm.pendley...>:
>>>>
>>>> You'd have far, far less trouble programming for the Mac if you'd
>>>> simply
>>>> learn how Cocoa works, instead of trying to reinvent .NET in
>>>> Objective-C.
>>>> When in Rome, do as the Romans do.
>>>
>>> That's why I asked in the first place. I didn't know how Cocoa works
>>> in regards to timers.
>>
>> I understand that - and it's a good point. But consider how you
>> asked the
>> question. If you don't know how Cocoa works, how is it that you've
>> already
>> decided that you shouldn't use a run loop? That's putting the cart
>> in front
>> of the horse, IMHO. The fact that you don't use a run loop to build
>> timers
>> with some other framework doesn't imply that you shouldn't do so
>> when you're
>> using Cocoa.
>
> I didn't really decide I shouldn't use a run loop for the timers. I am
> porting a library from another platform and just wanted a quick answer
> if I could get a similar timer API behavior in either Cocoa, Core
> Foundation or BSD Unix (with a preference on low-level for
> efficiency),
What make you think lower level mean more efficient ?
Just do it the simple way (CFRunLoopTimer) and if it not efficient
enough (after profiling, and testing), think about an other way to do
it.
But you will hardly find a difference between CFRunLoopTimer which are
a very thin wrapper in mach timers, and kevent's timers.


