You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

113 lines
2.4 KiB
C++

// SPDX-License-Identifier: BSD-2-Clause
// Copyright CM4all GmbH
// author: Max Kellermann <mk@cm4all.com>
#pragma once
#include "InotifyEvent.hxx"
#include "util/IntrusiveHashSet.hxx"
class InotifyManager;
/**
* Watch for one file. Managed by #InotifyManager.
*/
class InotifyWatch {
friend class InotifyManager;
IntrusiveHashSetHook<IntrusiveHookMode::NORMAL> watch_descriptor_hook;
InotifyManager &manager;
int watch_descriptor = -1;
bool oneshot;
public:
explicit InotifyWatch(InotifyManager &_manager) noexcept
:manager(_manager) {}
~InotifyWatch() noexcept {
RemoveWatch();
}
InotifyWatch(const InotifyWatch &) = delete;
InotifyWatch &operator=(const InotifyWatch &) = delete;
auto &GetManager() const noexcept {
return manager;
}
bool IsWatching() const noexcept {
return watch_descriptor >= 0;
}
bool TryAddWatch(const char *pathname, uint32_t mask) noexcept;
void AddWatch(const char *pathname, uint32_t mask);
void RemoveWatch() noexcept;
protected:
/**
* An inotify event was received.
*/
virtual void OnInotify(unsigned mask, const char *name) noexcept = 0;
};
/**
* Wrapper for #InotifyEvent with a watch descriptor manager.
*/
class InotifyManager final : InotifyHandler {
friend class InotifyWatch;
InotifyEvent event;
struct GetWatchDescriptor {
constexpr int operator()(const InotifyWatch &w) const noexcept {
return w.watch_descriptor;
}
};
IntrusiveHashSet<InotifyWatch, 1024,
IntrusiveHashSetOperators<InotifyWatch, GetWatchDescriptor,
std::hash<int>,
std::equal_to<int>>,
IntrusiveHashSetMemberHookTraits<&InotifyWatch::watch_descriptor_hook>> watches;
public:
/**
* Throws on error.
*/
explicit InotifyManager(EventLoop &event_loop);
~InotifyManager() noexcept;
auto &GetEventLoop() const noexcept {
return event.GetEventLoop();
}
/**
* Is the inotify file descriptor still open?
*/
bool IsDefined() const noexcept {
return event.IsDefined();
}
/**
* Initiate shutdown. This unregisters all #EventLoop events
* and prevents new ones from getting registered.
*/
void BeginShutdown() noexcept;
/**
* Has BeginShutdown() been called?
*/
bool IsShuttingDown() const noexcept {
return !event.IsDefined();
}
private:
// virtual methods from InotifyHandler
void OnInotify(int wd, unsigned mask, const char *name) override;
void OnInotifyError(std::exception_ptr error) noexcept override;
};