DEV Community

Cover image for Design folder change monitor in C++ (Windows)
Yash Hayaran
Yash Hayaran

Posted on

Design folder change monitor in C++ (Windows)

What's a hot folder?

Hot folder is like any other folder. Makes it hot is when a program (which we gonna code in C++) monitors the change.

Who uses it?

Software input can be file. File's source could be hardware like camera generating images or third-party software. Module watches a folder for change, to consume the input.

How to design?

Let's think! About what all we need:

We may heard about observer design pattern. Observers will get notified when a Subject updates. Observer design pattern fits well for this situation.

  • Watcher - Object responsible to receive events from OS about folder changes. Say watching the folder. Watcher is Subject, because Watcher behaves like subject, which gets update, and will notify the observers.

  • Update Listener - Object hold the list of changes received from Subject. Update Listener is Observer. Module listens to subject and adds the upcoming changes to thread safe collection. This is needed, why? Because assume a scenario where producer producing the N files per second, but when you don't have any listener like module then you may miss the events while processing the previous.

  • Handler - Object instantiate receiver and listener object respectively.

Let's start!

First we define our two basic interfaces 'ISubject' and 'IObject'

template <typename T>
class ISubject
{
    public:
        ISubject()          = default;
        virtual ~ISubject() = default;
        virtual AddObserver(const IObserver<T>* pObserver) = 0;
        virtual RemoveObserver(const IObserver<T>* pObserver) = 0;
        virtual NotifyObservers(const T& data) = 0;
};
Enter fullscreen mode Exit fullscreen mode
template <typename T>
class IObserver
{
    public:
        IObserver()          = default;
        virtual ~IObserver() = default;
        virtual Uptdate(const T& data) = 0;
};
Enter fullscreen mode Exit fullscreen mode
class DirectoryWatcher : public ISubject
{
    protected:
        std::string _strDirectory;
        HANDLE      _pChangeHandle;

        bool IsHandleValid();
        void Reset(const std::string& strDirectory);

    public: 
        DirectoryWatcher();
        ~DirectoryWatcher();

        bool Start(const std::string& strDirectory);
        void Stop();
        void AddObserver(const IObserver<std::string>* pObserver);
        void RemoveObserver(const IObserver<std::string>* pObserver);
        void NotifyObservers(const T& data);
};

Enter fullscreen mode Exit fullscreen mode
class UpdateListener : public IObserver
{
    protected:
        code_machina::BlockingCollection<std::string> _changeCollection;

    public: 
        UpdateListener();
        ~UpdateListener();

        bool Start(const std::string& strDirectory);
        void Stop();
        void AddObserver(const IObserver<std::string>* pObserver);
        void RemoveObserver(const IObserver<std::string>* pObserver);
        void NotifyObservers(const T& data);
};

Enter fullscreen mode Exit fullscreen mode

Please comment for more info!

Top comments (0)