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.