Browse Source

* Moved 'file_events' to project 'cppcore'

master
bergmann 4 years ago
parent
commit
a65a09059a
11 changed files with 0 additions and 637 deletions
  1. +0
    -1
      include/cppfs.h
  2. +0
    -15
      include/cppfs/file_events.h
  3. +0
    -59
      include/cppfs/file_events/fdset.h
  4. +0
    -63
      include/cppfs/file_events/fdset.inl
  5. +0
    -96
      include/cppfs/file_events/file_events.h
  6. +0
    -89
      include/cppfs/file_events/file_events.inl
  7. +0
    -68
      include/cppfs/file_events/select.h
  8. +0
    -114
      include/cppfs/file_events/select.inl
  9. +0
    -23
      include/cppfs/file_events/types.h
  10. +0
    -1
      test/cppfs/directory_tests.cpp
  11. +0
    -108
      test/cppfs/file_events_tests.cpp

+ 0
- 1
include/cppfs.h View File

@@ -3,5 +3,4 @@
#include <cppfs/config.h>
#include <cppfs/directory.h>
#include <cppfs/file.h>
#include <cppfs/file_events.h>
#include <cppfs/path.h>

+ 0
- 15
include/cppfs/file_events.h View File

@@ -1,15 +0,0 @@
#pragma once

#include <cppfs/config.h>

#include "file_events/file_events.h"

#if cppfs_os == cppfs_os_linux
#include "file_events/select.h"
#endif

#include "file_events/file_events.inl"

#if cppfs_os == cppfs_os_linux
#include "file_events/select.inl"
#endif

+ 0
- 59
include/cppfs/file_events/fdset.h View File

@@ -1,59 +0,0 @@
#pragma once

#include <sys/select.h>

namespace cppfs
{

struct fdset final
: public fd_set
{
public:
/**
* @brief Constructor.
*/
inline fdset();

/**
* @brief Check if any file descriptor is set in this set.
*
* @param[in] max_fd Largest file descriptor stored.
*
* @retval true If any file descriptor is set.
* @retval false If no file descriptor is set.
*/
inline bool is_any(int max_fd) const;

/**
* @brief Check if the passed file descriptor is set in this set.
*
* @param[in] fd File descriptor to check for.
*
* @retval true If the passed file descriptor is set.
* @retval false If the passed file descriptor is not set.
*/
inline bool is_set(int fd) const;

/**
* @brief Set the passed file descriptor in the set.
*
* @param[in] fd File descriptor to set.
*/
inline void set(int fd);

/**
* @brief Clear the passed file descriptor in the set.
*
* @param[in] fd File descriptor to clear.
*/
inline void clear(int fd);

/**
* @brief Clear the complete file descriptor set.
*/
inline void reset();
};

}

#include "fdset.inl"

+ 0
- 63
include/cppfs/file_events/fdset.inl View File

@@ -1,63 +0,0 @@
#pragma once

#include "fdset.h"

namespace cppfs
{

/* fdset */

static_assert(
sizeof(fd_set) == sizeof(fdset),
"Size of fd set implementation does not match.");

fdset::fdset()
{
FD_ZERO(this);
}

bool fdset::is_any(int max_fd) const
{
static constexpr int field_count = sizeof(fds_bits) / sizeof(fds_bits[0]);

if (max_fd >= FD_SETSIZE)
throw cppcore::exception("Size of fd set exceeded!");

if (max_fd < 0)
return false;

auto cnt = (max_fd / field_count) + 1;
for (int i = 0; i < cnt; ++i)
{
if (fds_bits[i])
return true;
}

return false;
}

bool fdset::is_set(int fd) const
{
if (fd >= FD_SETSIZE)
throw cppcore::exception("Size of fd set exceeded!");
return FD_ISSET(fd, this);
}

void fdset::set(int fd)
{
if (fd >= FD_SETSIZE)
throw cppcore::exception("Size of fd set exceeded!");
FD_SET(fd, this);
}

void fdset::clear(int fd)
{
if (fd >= FD_SETSIZE)
throw cppcore::exception("Size of fd set exceeded!");
FD_CLR(fd, this);
}

void fdset::reset()
{ FD_ZERO(this); }

}

+ 0
- 96
include/cppfs/file_events/file_events.h View File

@@ -1,96 +0,0 @@
#pragma once

#include <cppfs/misc.h>

#include "types.h"

namespace cppfs
{

template<typename T_impl>
struct file_events
{
public:
using impl_type = T_impl;
using result_impl_type = typename impl_type::result_type;

struct result
{
private:
result_impl_type _impl;

public:
/**
* @brief Constructor.
*/
template<typename X_impl>
inline result(X_impl&& p_impl);

/**
* @brief Check if any event has occured in any handle.
*/
bool is_set() const;

/**
* @brief Check if any event has occured in the passed handle.
*/
bool is_set(
const raw_handle& p_handle) const;

/**
* @brief Check if any of the passed event has occured in any handle.
*/
bool is_set(
const event_types& p_events) const;

/**
* @brief Check if any of the passed event has occured in the passed handle.
*/
bool is_set(
const event_types& p_events,
const raw_handle& p_handle) const;
};

private:
impl_type _impl;

public:
/**
* @brief Constructor.
*/
inline file_events();

/**
* @brief Add or change a event listener for the passed file.
*/
inline void add(
const raw_handle& p_handle,
const event_types& p_events);

/**
* @brief Remove the event listener for the passed file.
*/
inline void erase(
const raw_handle& p_handle);

/**
* @brief Reset all event listeners.
*/
inline void reset();

/**
* @brief Wait for file events and return the result.
*/
inline result wait(
const event_timeout * p_timeout) const;

/**
* @brief Wait for file events and call the passed callback for each event.
*/
template<typename T_lambda>
inline void wait(
T_lambda&& p_lambda,
const event_timeout * p_timeout) const;
};

}

+ 0
- 89
include/cppfs/file_events/file_events.inl View File

@@ -1,89 +0,0 @@
#pragma once

#include "file_events.h"

namespace cppfs
{

/* file_events::result */

template<typename T_impl>
template<typename X_impl>
file_events<T_impl>::result::result(X_impl&& p_impl)
: _impl(std::forward<X_impl>(p_impl))
{ }

template<typename T_impl>
bool file_events<T_impl>::result::is_set() const
{
static const event_types all_types({
event_type::read,
event_type::write,
event_type::except,
});
return _impl.is_set(all_types, nullptr);
}

template<typename T_impl>
bool file_events<T_impl>::result::is_set(
const raw_handle& p_handle) const
{
static const event_types all_types({
event_type::read,
event_type::write,
event_type::except,
});
return _impl.is_set(all_types, &p_handle);
}

template<typename T_impl>
bool file_events<T_impl>::result::is_set(
const event_types& p_events) const
{
return _impl.is_set(p_events, nullptr);
}

template<typename T_impl>
bool file_events<T_impl>::result::is_set(
const event_types& p_events,
const raw_handle& p_handle) const
{
return _impl.is_set(p_events, &p_handle);
}

/* file_events */

template<typename T_impl>
file_events<T_impl>::file_events()
: _impl()
{ }

template<typename T_impl>
void file_events<T_impl>::add(
const raw_handle& p_handle,
const event_types& p_events)
{ _impl.add(p_handle, p_events); }

template<typename T_impl>
void file_events<T_impl>::erase(
const raw_handle& p_handle)
{ _impl.erase(p_handle); }

template<typename T_impl>
void file_events<T_impl>::reset()
{ _impl = impl_type(); }

template<typename T_impl>
typename file_events<T_impl>::result
file_events<T_impl>::wait(
const event_timeout * p_timeout) const
{ return result(_impl.wait(p_timeout)); }

template<typename T_impl>
template<typename T_lambda>
void file_events<T_impl>::wait(
T_lambda&& p_lambda,
const event_timeout * p_timeout) const
{ _impl.wait(std::forward<T_lambda>(p_lambda), p_timeout); }

}

+ 0
- 68
include/cppfs/file_events/select.h View File

@@ -1,68 +0,0 @@
#pragma once

#include <sys/select.h>

#include <cppfs/file/file.h>

#include "types.h"
#include "fdset.h"

namespace cppfs
{

struct fe_select
{
public:
struct storage
{
int max_fd { -1 };
fdset read;
fdset write;
fdset except;

inline bool is_set(
const event_types& p_events,
const raw_handle* p_handle) const;
};

using result_type = storage;

private:
storage _storage;

public:
/**
* @brief Constructor.
*/
inline fe_select() = default;

public: /* file_events implementation */
/**
* @brief Add or change a event listener for the passed file.
*/
inline void add(
const raw_handle& p_handle,
const event_types& p_events);

/**
* @brief Remove the event listener for the passed handle.
*/
inline void erase(
const raw_handle& p_handle);

/**
* @brief Wait for file events and return the result.
*/
inline result_type wait(
const event_timeout * p_timeout) const;

/**
* @brief Wait for file events and call the passed callback for each event.
*/
template<typename T_lambda>
inline void wait(
T_lambda&& p_lambda,
const event_timeout * p_timeout) const;
};

}

+ 0
- 114
include/cppfs/file_events/select.inl View File

@@ -1,114 +0,0 @@
#pragma once

#include <cppcore/conversion/time.h>

#include "select.h"

namespace cppfs
{

/* fe_select::storage */

bool fe_select::storage::is_set(
const event_types& p_events,
const raw_handle* p_handle) const
{
if (p_handle)
{
auto fd = p_handle->handle();
return (p_events.is_set(event_type::read) && read.is_set(fd))
|| (p_events.is_set(event_type::write) && write.is_set(fd))
|| (p_events.is_set(event_type::except) && except.is_set(fd));
}
else
{
return (p_events.is_set(event_type::read) && read.is_any(max_fd))
|| (p_events.is_set(event_type::write) && write.is_any(max_fd))
|| (p_events.is_set(event_type::except) && except.is_any(max_fd));
}
}

/* fe_select */

void fe_select::add(
const raw_handle& p_handle,
const event_types& p_events)
{
int fd = p_handle.handle();
if (fd < 0)
throw cppcore::exception("The passed file is not opened!");

if (p_events.is_set(event_type::read)) _storage.read.set(fd);
if (p_events.is_set(event_type::write)) _storage.write.set(fd);
if (p_events.is_set(event_type::except)) _storage.except.set(fd);

if ( !_storage.read.is_set(fd)
&& !_storage.write.is_set(fd)
&& !_storage.except.is_set(fd))
throw cppcore::exception("No or unkown events passed!");

_storage.max_fd = std::max(fd, _storage.max_fd);
}

void fe_select::erase(const raw_handle& p_handle)
{
int fd = p_handle.handle();
if (fd < 0)
throw cppcore::exception("The passed file is not opened!");

_storage.read.clear(fd);
_storage.write.clear(fd);
_storage.except.clear(fd);

if (fd == _storage.max_fd)
{
while (_storage.max_fd >= 0
&& !_storage.read.is_set(_storage.max_fd)
&& !_storage.write.is_set(_storage.max_fd)
&& !_storage.except.is_set(_storage.max_fd))
--_storage.max_fd;
}
}

fe_select::result_type fe_select::wait(const event_timeout * p_timeout) const
{
auto ret = _storage;

struct timespec timeout { 0, 0 };
if (p_timeout)
{
auto now = std::chrono::steady_clock::now();
if (now < *p_timeout)
{
auto diff = *p_timeout - now;
timeout = cppcore::duration_cast<timespec>(diff);
}
}

if (::pselect(ret.max_fd + 1, &ret.read, &ret.write, &ret.except, p_timeout ? &timeout : nullptr, nullptr) < 0)
{
auto err = errno;
if (err != EINTR)
throw cppcore::error_exception("Error while fetching file events with 'select'", err);
}

return ret;
}

template<typename T_lambda>
void fe_select::wait(T_lambda&& p_lambda, const event_timeout * p_timeout) const
{
auto ret = wait(p_timeout);
for (auto fd = 0; fd <= ret.max_fd; ++fd)
{
event_types ev;
if (ret.read.is_set(fd)) ev.set(event_type::read);
if (ret.write.is_set(fd)) ev.set(event_type::write);
if (ret.except.is_set(fd)) ev.set(event_type::except);

if (ev)
p_lambda(fd, ev);
}
}

}

+ 0
- 23
include/cppfs/file_events/types.h View File

@@ -1,23 +0,0 @@
#pragma once

#include <chrono>

#include <cppcore/misc/flags.h>

namespace cppfs
{

enum class event_type
{
unknown = 0,
read,
write,
except,
};

using event_types = cppcore::shifted_flags<event_type>;

using event_clock = std::chrono::steady_clock;
using event_timeout = event_clock::time_point;

}

+ 0
- 1
test/cppfs/directory_tests.cpp View File

@@ -31,7 +31,6 @@ TEST(directory_tests, iterator)
files,
std::vector<std::string>({
"directory_tests.cpp",
"file_events_tests.cpp",
"file_tests.cpp",
"path_tests.cpp",
}));


+ 0
- 108
test/cppfs/file_events_tests.cpp View File

@@ -1,108 +0,0 @@
#include <gtest/gtest.h>

#include <fstream>

#include <cppfs.h>

using namespace ::testing;
using namespace ::cppfs;

struct pipe_handle
: public raw_handle
{
pipe_handle(int p_handle)
{
_handle = p_handle;
}

~pipe_handle()
{
close(_handle);
}
};

TEST(file_events_tests, select_with_callback)
{
int fds[2];
ASSERT_EQ(0, pipe(fds));

pipe_handle read_handle(fds[0]);
pipe_handle write_handle(fds[1]);

file_events<fe_select> fe;

fe.add(read_handle, event_types::all());
fe.add(write_handle, event_types::all());

auto timeout = event_clock::now();
fe.wait(
[&](auto fd, auto events) {
EXPECT_EQ(fd, write_handle.handle());
},
&timeout);

write(write_handle.handle(), "fuuu", 4);

auto i = 0;
fe.wait(
[&](auto fd, auto events) {
switch (i)
{
case 0:
EXPECT_EQ(fd, read_handle.handle());
EXPECT_EQ(events, event_types(event_type::read));
break;
case 1:
EXPECT_EQ(fd, write_handle.handle());
EXPECT_EQ(events, event_types(event_type::write));
break;
}
++i;
},
&timeout);
}


TEST(file_events_tests, select_with_result)
{
int fds[2];
ASSERT_EQ(0, pipe(fds));

pipe_handle read_handle(fds[0]);
pipe_handle write_handle(fds[1]);

file_events<fe_select> fe;

fe.add(read_handle, event_types::all());
fe.add(write_handle, event_types::all());

auto timeout = event_clock::now();

auto ret = fe.wait(&timeout);

EXPECT_TRUE (ret.is_set());
EXPECT_FALSE(ret.is_set(event_type::read));
EXPECT_TRUE (ret.is_set(event_type::write));
EXPECT_FALSE(ret.is_set(event_type::except));
EXPECT_FALSE(ret.is_set(event_type::read, read_handle));
EXPECT_FALSE(ret.is_set(event_type::write, read_handle));
EXPECT_FALSE(ret.is_set(event_type::except, read_handle));
EXPECT_FALSE(ret.is_set(event_type::read, write_handle));
EXPECT_TRUE (ret.is_set(event_type::write, write_handle));
EXPECT_FALSE(ret.is_set(event_type::except, write_handle));

write(write_handle.handle(), "fuuu", 4);

ret = fe.wait(&timeout);

EXPECT_TRUE (ret.is_set());
EXPECT_TRUE (ret.is_set(event_type::read));
EXPECT_TRUE (ret.is_set(event_type::write));
EXPECT_FALSE(ret.is_set(event_type::except));
EXPECT_TRUE (ret.is_set(event_type::read, read_handle));
EXPECT_FALSE(ret.is_set(event_type::write, read_handle));
EXPECT_FALSE(ret.is_set(event_type::except, read_handle));
EXPECT_FALSE(ret.is_set(event_type::read, write_handle));
EXPECT_TRUE (ret.is_set(event_type::write, write_handle));
EXPECT_FALSE(ret.is_set(event_type::except, write_handle));
}

Loading…
Cancel
Save