×

Discussion Board

Results 1 to 2 of 2
  1. #1
    Registered User
    Join Date
    Nov 2004
    Posts
    14

    unexpected ao_sleep behavior

    Can someone explain to me why this doesn't work?

    Code:
    import e32
    
    def task1():
        print "[task1] waiting"
        lock.wait()
        print "[task1] revived"
    
    lock = e32.Ao_lock()
    e32.ao_sleep(0, task1)
    
    print "[main] sleeping"
    e32.ao_sleep(1)
    
    print "[main] signalling"
    lock.signal()
    
    print "[main] done"
    The output I get is:
    Code:
    [main] sleeping
    [task1] waiting
    and then it hangs. ao_sleep(1) never returns.

    But this does work, and I don't know why:
    Code:
    import e32
    
    def task1():
        print "[task1] waiting"
        lock.wait()
        print "[task1] revived"
    
    lock = e32.Ao_lock()
    e32.ao_sleep(0, task1)
    
    print "[main] sleeping"
    
    def signal():
        print "[main] signalling"
        lock.signal()
    
    e32.ao_sleep(1, signal)
    e32.ao_sleep(1)
    
    print "[main] done"
    Here, the output is:
    Code:
    [main] sleeping
    [task1] waiting
    [main] signalling
    [task1] revived
    [main] done
    and the program exits gracefully.

    Thanks in advance.

  2. #2
    Super Contributor
    Join Date
    Dec 2004
    Posts
    643
    Originally posted by relbs
    Can someone explain to me why this doesn't work?

    Code:
    import e32
    
    def task1():
        print "[task1] waiting"
        lock.wait()
        print "[task1] revived"
    
    lock = e32.Ao_lock()
    e32.ao_sleep(0, task1)
    
    print "[main] sleeping"
    e32.ao_sleep(1)
    
    print "[main] signalling"
    lock.signal()
    
    print "[main] done"
    The output I get is:
    Code:
    [main] sleeping
    [task1] waiting
    and then it hangs. ao_sleep(1) never returns.

    But this does work, and I don't know why:
    Code:
    import e32
    
    def task1():
        print "[task1] waiting"
        lock.wait()
        print "[task1] revived"
    
    lock = e32.Ao_lock()
    e32.ao_sleep(0, task1)
    
    print "[main] sleeping"
    
    def signal():
        print "[main] signalling"
        lock.signal()
    
    e32.ao_sleep(1, signal)
    e32.ao_sleep(1)
    
    print "[main] done"
    Here, the output is:
    Code:
    [main] sleeping
    [task1] waiting
    [main] signalling
    [task1] revived
    [main] done
    and the program exits gracefully.

    Thanks in advance.
    This is actually quite hard to explain, since there's more magic happening there than you may realize. The short version is that if you want to avoid trouble, never wait for an Ao_lock inside a callback from the native side.

    For those familiar with Symbian this behaviour is due to the fact that e32.Ao_lock and e32.ao_sleep() both create an Active Object that gets run when their respective conditions are fulfilled. Ao_lock.wait() and e32.ao_sleep() (without a callback given) then both start a nested Active Scheduler loop that runs until the Active Object they own is run. In the code above
    e32.ao_sleep(0, task1) sets up a RTimer Active Object and e32.ao_sleep(1) starts an Active Scheduler that immediately runs task1(). The lock.wait() then starts _another_ scheduler loop that will hang forever waiting for the lock to be signalled. Program execution never gets to the lock.signal() line, since to get there you would first have to leave task1().

    I'll try to find time to write a more understandable explanation later. In the mean time people familiar with Symbian Active Objects are welcome to translate the above into a human language.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •