Re: callback never invoked

2020-10-25 Thread Marc Lehmann
On Sun, Oct 18, 2020 at 02:46:44PM +0500, rustahm  wrote:
> libev++ to watch a directory of files and call the callback function as
> soon as inotify gives at least one relevant event. And I don't want libev++
> to block my main program, that's why I tried to use it with NOWAIT.

All event libraries block at least one thread. You coulöd move that into
something other than your main thread, but that complicates things so I would
not reocmmend that.

> Am I doing it totally wrong? Is libev++ a right tool for the task?

I am not sure what you are trying to achieve, but libev (not libev++) does
kind of impose event-based programming on the user. You could use it
differently, but that would be very advanced, and possibly also painful.

So if you can't use an event-based approach and do you work in callbacks,
libev (or any other event library) would be the wrong tool.

> If I add ev_run(EV_A_ 0); to engage_watcher() I get use of undeclared
> identifier 'loop'.

You cna either use "ev_run (ev_default_loop (), 0)" or, if you have more
than one loop, pass the "struct ev_loop *" around. There is also a macro
you can use "ev_run (EV_DEFAULT_UC_ 0)" that is faster than calling
ev_default_loop if the loop is guartanteed to be initialiased already.

> and run the program but it gets blocked until I change a file in the
> directory being watched.

Yes, that's how it works. You need to cal ev_run in your main program and
do your work in callbacks, always returning to the main loop.

-- 
The choice of a   Deliantra, the free code+content MORPG
  -==- _GNU_  http://www.deliantra.net
  ==-- _   generation
  ---==---(_)__  __   __  Marc Lehmann
  --==---/ / _ \/ // /\ \/ /  schm...@schmorp.de
  -=/_/_//_/\_,_/ /_/\_\

___
libev mailing list
libev@lists.schmorp.de
http://lists.schmorp.de/mailman/listinfo/libev


Re: callback never invoked

2020-10-18 Thread rustahm
Thank you, Marc, for your input. This is my first time using such a
library, so I guess I don't get your point.

My main program should only receive a list of relevant events from inotify
and process them through a callback function of the main program. I want
libev++ to watch a directory of files and call the callback function as
soon as inotify gives at least one relevant event. And I don't want libev++
to block my main program, that's why I tried to use it with NOWAIT.

Am I doing it totally wrong? Is libev++ a right tool for the task?

If I add ev_run(EV_A_ 0); to engage_watcher() I get use of undeclared
identifier 'loop'. If I also add ev::default_loop loop; then I can build
and run the program but it gets blocked until I change a file in the
directory being watched. And even after that the program's window doesn't
show up.

If I replace 0 with EVRUN_NOWAIT then the window shows up but io_callback()
is never invoked again.

How can I get it working?

On Mon, Oct 12, 2020 at 2:51 PM Marc Lehmann  wrote:

> On Sun, Oct 11, 2020 at 04:51:09PM +0500, rustahm 
> wrote:
> > Please find attached the source code. Could anyone explain why the
> callback
> > is never invoked when I do change the files?
>
> You probably never call ev's mainloop: you only call ev::run once with
> NOWAIT, so unless any change happens before that call, libev code is never
> invoked and therefore does not have a chance of calling your callback.
>
> You would need to put something like ev_run (EV_A_ 0) into your main
> program
> (which you haven't shown).
>
> Also, ev::get_default_loop() (and .run) is internal undocumented
> functionality which you should not call if you want your program to
> continue to work with future versions.
>
> --
> The choice of a   Deliantra, the free code+content
> MORPG
>   -==- _GNU_  http://www.deliantra.net
>   ==-- _   generation
>   ---==---(_)__  __   __  Marc Lehmann
>   --==---/ / _ \/ // /\ \/ /  schm...@schmorp.de
>   -=/_/_//_/\_,_/ /_/\_\
>
___
libev mailing list
libev@lists.schmorp.de
http://lists.schmorp.de/mailman/listinfo/libev


Re: callback never invoked

2020-10-12 Thread Marc Lehmann
On Sun, Oct 11, 2020 at 04:51:09PM +0500, rustahm  wrote:
> Please find attached the source code. Could anyone explain why the callback
> is never invoked when I do change the files?

You probably never call ev's mainloop: you only call ev::run once with
NOWAIT, so unless any change happens before that call, libev code is never
invoked and therefore does not have a chance of calling your callback.

You would need to put something like ev_run (EV_A_ 0) into your main program
(which you haven't shown).

Also, ev::get_default_loop() (and .run) is internal undocumented
functionality which you should not call if you want your program to
continue to work with future versions.

-- 
The choice of a   Deliantra, the free code+content MORPG
  -==- _GNU_  http://www.deliantra.net
  ==-- _   generation
  ---==---(_)__  __   __  Marc Lehmann
  --==---/ / _ \/ // /\ \/ /  schm...@schmorp.de
  -=/_/_//_/\_,_/ /_/\_\

___
libev mailing list
libev@lists.schmorp.de
http://lists.schmorp.de/mailman/listinfo/libev


callback never invoked

2020-10-11 Thread rustahm
Hello,

Please find attached the source code. Could anyone explain why the callback
is never invoked when I do change the files?

Thank you,

Roustam
// custom
#include "watcher.h"
// standard
#include 
// cross-platform
#include 
// Linux
#include 
#include 
#include 
#include 

std::string dir_path;
int file_descriptor, watch_descriptor;
ev::io watcher;
std::list events;

static void io_callback (ev::io &event_watcher, int revents) {
	events.clear();
	char buffer[4096] __attribute__ ((aligned(__alignof__(struct inotify_event;
	const struct inotify_event *p_file_event;
	std::size_t event_size = sizeof(struct inotify_event);
	struct stat metadata;
	while (true) {
		ssize_t bytes_count = read(file_descriptor, buffer, sizeof buffer);
		if (bytes_count == -1) {// no new events to process, exit the loop
			if (errno != EAGAIN)
std::perror("read");
			break;
		}
		// process new events
		for (char *p_event = buffer, *end = buffer + bytes_count; p_event < end; p_event += event_size + p_file_event->len) {
			p_file_event = (const struct inotify_event *) p_event;
			if (!(p_file_event->mask & IN_ISDIR) && p_file_event->len) {// the file is not a directory and has a name
Event file_event;
file_event.name = p_file_event->name;
if (p_file_event->mask & IN_DELETE || p_file_event->mask & IN_MOVED_FROM)// the file was removed
	file_event.status = removed;
else if(stat((dir_path + '/' + file_event.name).c_str(), &metadata) != -1) {// successfully got file metadata
	file_event.size = (long long) metadata.st_size;
	file_event.modified = ctime(&metadata.st_mtime);
	if (p_file_event->mask & IN_MODIFY || p_file_event->mask & IN_MOVED_TO)// the file was created or modified
		file_event.status = modified;
	else// dismiss the event
		continue;
}
else// dismiss the event
	continue;
events.push_back(file_event);
			}
		}
	}
}

std::list engage_watcher(const std::string &directory_path) {
	std::list result;
	if (!dir_path.empty())
		return result;
	struct stat metadata;
	struct dirent *entry = nullptr;// a file
	// open the directory
	DIR *directory = nullptr;
	directory = opendir(directory_path.c_str());
	if (directory != nullptr) {
		dir_path = directory_path;
		// initialize a file descriptor
		file_descriptor = inotify_init1(IN_NONBLOCK);
		if (file_descriptor == -1) {
			std::perror("inotify_init1");
			return result;
		}
		// initialize a watch descriptor
		watch_descriptor = inotify_add_watch(file_descriptor, dir_path.c_str(), IN_MODIFY | IN_MOVED_TO | IN_DELETE | IN_MOVED_FROM);
		if (watch_descriptor == -1) {
			std::fprintf(stderr, "Cannot watch the directory. Error: %s\en", std::strerror(errno));
			close(file_descriptor);
			return result;}
		// iterate through all files in the watched directory
		while ((entry = readdir(directory))) {// get next file from the watched directory
			if (entry->d_type != 4) {// the file is not a directory
if (stat((dir_path + '/' + entry->d_name).c_str(), &metadata) != -1) {// get file metadata
	Event file_event;
	file_event.name = entry->d_name;
	file_event.size = (long long) metadata.st_size;
	file_event.modified = ctime(&metadata.st_mtime);
	file_event.status = modified;
	result.push_back(file_event);
}
			}
		}
		// set the callback for the watcher and start watching
		watcher.set  ();
		watcher.start(file_descriptor, ev::READ);
		ev::get_default_loop().run(EVRUN_NOWAIT);
	}
	closedir(directory);
	return result;
}

void disengage_watcher() {
	if (dir_path.empty())
		return;
	watcher.stop();
	dir_path.clear();
	inotify_rm_watch(file_descriptor, watch_descriptor);
	close(file_descriptor);
	return;
}
#ifndef WATCHER_H
#define WATCHER_H

// standard
#include 
#include 

enum FileStatus {modified, removed};

struct Event {
	std::string modified;
	std::string name;
	long long size;
	FileStatus status;
};

std::list engage_watcher(const std::string &directory_path);
void disengage_watcher();

#endif // WATCHER_H
___
libev mailing list
libev@lists.schmorp.de
http://lists.schmorp.de/mailman/listinfo/libev