root/headers/os/app/Looper.h
/*
 * Copyright 2001-2015 Haiku, Inc. All rights reserved.
 * Distributed under the terms of the MIT License.
 *
 * Authors:
 *              Erik Jaesler, erik@cgsoftware.com
 */
#ifndef _LOOPER_H
#define _LOOPER_H


#include <BeBuild.h>
#include <Handler.h>
#include <List.h>
#include <OS.h>


class BMessage;
class BMessageQueue;
namespace BPrivate {
        class BDirectMessageTarget;
        class BLooperList;
}

// Port (Message Queue) Capacity
#define B_LOOPER_PORT_DEFAULT_CAPACITY  200


class BLooper : public BHandler {
public:
                                                        BLooper(const char* name = NULL,
                                                                int32 priority = B_NORMAL_PRIORITY,
                                                                int32 portCapacity
                                                                        = B_LOOPER_PORT_DEFAULT_CAPACITY);
        virtual                                 ~BLooper();

        // Archiving
                                                        BLooper(BMessage* data);
        static  BArchivable*    Instantiate(BMessage* data);
        virtual status_t                Archive(BMessage* data, bool deep = true) const;

        // Message transmission
                        status_t                PostMessage(uint32 command);
                        status_t                PostMessage(BMessage* message);
                        status_t                PostMessage(uint32 command, BHandler* handler,
                                                                BHandler* replyTo = NULL);
                        status_t                PostMessage(BMessage* message, BHandler* handler,
                                                                BHandler* replyTo = NULL);

        virtual void                    DispatchMessage(BMessage* message,
                                                                BHandler* handler);
        virtual void                    MessageReceived(BMessage* message);
                        BMessage*               CurrentMessage() const;
                        BMessage*               DetachCurrentMessage();
                        void                    DispatchExternalMessage(BMessage* message,
                                                                BHandler* handler, bool& _detached);
                        BMessageQueue*  MessageQueue() const;
                        bool                    IsMessageWaiting() const;

        // Message handlers
                        void                    AddHandler(BHandler* handler);
                        bool                    RemoveHandler(BHandler* handler);
                        int32                   CountHandlers() const;
                        BHandler*               HandlerAt(int32 index) const;
                        int32                   IndexOf(BHandler* handler) const;

                        BHandler*               PreferredHandler() const;
                        void                    SetPreferredHandler(BHandler* handler);

        // Loop control
        virtual thread_id               Run();
                        void                    Loop();
        virtual void                    Quit();
        virtual bool                    QuitRequested();
                        bool                    Lock();
                        void                    Unlock();
                        bool                    IsLocked() const;
                        status_t                LockWithTimeout(bigtime_t timeout);
                        thread_id               Thread() const;
                        team_id                 Team() const;
        static  BLooper*                LooperForThread(thread_id thread);

        // Loop debugging
                        thread_id               LockingThread() const;
                        int32                   CountLocks() const;
                        int32                   CountLockRequests() const;
                        sem_id                  Sem() const;

        // Scripting
        virtual BHandler*               ResolveSpecifier(BMessage* message, int32 index,
                                                                BMessage* specifier, int32 what,
                                                                const char* property);
        virtual status_t                GetSupportedSuites(BMessage* data);

        // Message filters (also see BHandler).
        virtual void                    AddCommonFilter(BMessageFilter* filter);
        virtual bool                    RemoveCommonFilter(BMessageFilter* filter);
        virtual void                    SetCommonFilterList(BList* filters);
                        BList*                  CommonFilterList() const;

        // Private or reserved
        virtual status_t                Perform(perform_code d, void* arg);

protected:
                // called from overridden task_looper
                        BMessage*               MessageFromPort(bigtime_t = B_INFINITE_TIMEOUT);

private:
        typedef BHandler _inherited;
        friend class BWindow;
        friend class BApplication;
        friend class BMessenger;
        friend class BView;
        friend class BHandler;
        friend class ::BPrivate::BLooperList;
        friend port_id _get_looper_port_(const BLooper* );

        virtual void                    _ReservedLooper1();
        virtual void                    _ReservedLooper2();
        virtual void                    _ReservedLooper3();
        virtual void                    _ReservedLooper4();
        virtual void                    _ReservedLooper5();
        virtual void                    _ReservedLooper6();

                                                        BLooper(const BLooper&);
                        BLooper&                operator=(const BLooper&);

                                                        BLooper(int32 priority, port_id port,
                                                                const char* name);

                        status_t                _PostMessage(BMessage* msg, BHandler* handler,
                                                                BHandler* reply_to);

        static  status_t                _Lock(BLooper* loop, port_id port,
                                                                bigtime_t timeout);
        static  status_t                _LockComplete(BLooper* loop, int32 old,
                                                                thread_id this_tid, sem_id sem,
                                                                bigtime_t timeout);
                        void                    _InitData(const char* name, int32 priority,
                                                                port_id port, int32 capacity);
                        void                    AddMessage(BMessage* msg);
                        void                    _AddMessagePriv(BMessage* msg);
        static  status_t                _task0_(void* arg);

                        void*                   ReadRawFromPort(int32* code,
                                                                bigtime_t timeout = B_INFINITE_TIMEOUT);
                        BMessage*               ReadMessageFromPort(
                                                                bigtime_t timeout = B_INFINITE_TIMEOUT);
        virtual BMessage*               ConvertToMessage(void* raw, int32 code);
        virtual void                    task_looper();
                        void                    _QuitRequested(BMessage* msg);
                        bool                    AssertLocked() const;
                        BHandler*               _TopLevelFilter(BMessage* msg, BHandler* target);
                        BHandler*               _HandlerFilter(BMessage* msg, BHandler* target);
                        BHandler*               _ApplyFilters(BList* list, BMessage* msg,
                                                                BHandler* target);
                        void                    check_lock();
                        BHandler*               resolve_specifier(BHandler* target, BMessage* msg);
                        void                    UnlockFully();

                        ::BPrivate::BDirectMessageTarget* fDirectTarget;
                        BMessage*               fLastMessage;
                        port_id                 fMsgPort;
                        int32                   fAtomicCount;
                        sem_id                  fLockSem;
                        int32                   fOwnerCount;
                        thread_id               fOwner;
                        thread_id               fThread;
                        addr_t                  fCachedStack;
                        int32                   fInitPriority;
                        BHandler*               fPreferred;
                        BList                   fHandlers;
                        BList*                  fCommonFilters;
                        bool                    fTerminating;
                        bool                    fRunCalled;
                        bool                    fOwnsPort;
                        uint32                  _reserved[11];
};

#endif  // _LOOPER_H