Overview
Examples
Screenshots
Comparisons
Applications
Download
Documentation
Tutorials
Bazaar
Status & Roadmap
FAQ
Authors & License
Forums
Funding Ultimate++
Search on this site
Search in forums












SourceForge.net Logo
Home » U++ TheIDE » U++ TheIDE: Other Features Wishlist and/or Bugs » [Fixed] TheIde continuously using CPU
Re: TheIde continuously using CPU [message #60155 is a reply to message #60153] Fri, 15 September 2023 03:46 Go to previous message
jjacksonRIAB is currently offline  jjacksonRIAB
Messages: 221
Registered: June 2011
Experienced Member
Any chance of using inotify instead? I wrote some example code that appears to work but likely has bugs and could probably be written better.

#include <Core/Core.h>
#include <ide/Core/Core.h>
#include <sys/inotify.h>

using namespace Upp;

void GatherAllFiles(const String& path, Index<String>& filei, VectorMap<String, String>& file)
{
    Sleep(0); // This is supposed to be superlazy
    for(FindFile ff(path + "/*.*"); ff && !Thread::IsShutdownThreads(); ff.Next())
        if(ff.IsFolder() && *ff.GetName() != '.')
            GatherAllFiles(ff.GetPath(), filei, file);
        else
        if(ff.IsFile()) {
            String p = NormalizePath(ff.GetPath());
            String lp = ToLower(p);
            if(filei.Find(lp) < 0) {
                filei.Add(lp);
                file.Add(GetFileName(p), p);
            }
        }
}

class INotify {
    int           fd          {};
    Index<String> directories {};
    Buffer<char>  buffer      {};
    Index<int>    watches     {};
    
    const int BUFFER_SIZE = 4096;
    
    Vector<String> add;
    Vector<String> remove;
    
public:
    void AddWatch(String directory) {
        add.Add(directory);
        
        if(directories.Find(directory) < 0) {
            auto wd = inotify_add_watch(fd, directory, IN_CREATE | IN_DELETE | IN_DELETE_SELF | IN_MOVED_TO | IN_MOVED_FROM | IN_CLOSE_WRITE);
            
            if(wd == -1) {
                LOG("watch failed!");
                return;
            }
            
            directories.Add(directory);
            watches.Add(wd);
        }
    }
    
    void AddWatchRecursive(String path) {
        AddWatch(path);
        
        for(FindFile ff(path + "/*.*"); ff && !Thread::IsShutdownThreads(); ff.Next()) {
            if(ff.IsFolder() && *ff.GetName() != '.') {
                AddWatchRecursive(ff.GetPath());
            }
        }
    }
    
    void RemoveWatch(String directory) {
        auto idx = directories.Find(directory);
        
        if(idx >= 0) {
            inotify_rm_watch(fd, watches[idx]);
            directories.Unlink(idx);
            watches.Unlink(idx);
        }
    }
    
    void Run() {
        const size_t EVENT_SIZE     = ( sizeof (struct inotify_event) );
        const size_t EVENT_BUF_LEN  = ( 1024 * ( EVENT_SIZE + 16 ) );
        
        ssize_t numBytes = read(fd, buffer.begin(), BUFFER_SIZE);
        
        if(numBytes == -1 && errno != EAGAIN) {
            LOG("read failed!");
        }
        
        struct inotify_event* event = reinterpret_cast<struct inotify_event*>(buffer.begin());
        
        int i = 0;
        
        while(i < numBytes) {
            struct inotify_event *event = ( struct inotify_event * ) &buffer[i];
            
            auto idx = watches.Find(event->wd);
            
            if(idx < 0) break;
            
            String name = directories[idx];
            name.Cat("/");
            name.Cat(event->name);
            
            LOG(name);
            
            if(event->mask & IN_ISDIR) {
                if(event->mask & IN_CREATE) {
                    DirCreated(name);
                }
                else if(event->mask & IN_DELETE) {
                    DirDeleted(name);
                }
                else if(event->mask & IN_DELETE_SELF) {
                    DirDeleted(name);
                }
                else if(event->mask & IN_MOVED_FROM) {
                    DirMovedFrom(name);
                }
                else if(event->mask & IN_MOVED_TO) {
                    DirMovedTo(name);
                }
            }
            else {
                if(event->mask & IN_CREATE) {
                    FileCreated(name);
                }
                else if(event->mask & IN_DELETE) {
                    FileDeleted(name);
                }
                else if(event->mask & IN_MOVED_FROM) {
                    FileMovedFrom(name);
                }
                else if(event->mask & IN_MOVED_TO) {
                    FileMovedTo(name);
                }
            }
            
            i += EVENT_SIZE + event->len;
        }
        
        directories.Sweep();
        watches.Sweep();
    }
    
    INotify() : fd(inotify_init1(IN_NONBLOCK)) {
        if(!fd) {
            LOG("inotify failed!");
        }
        
        LOG("inotify started");
        buffer.Alloc(BUFFER_SIZE);
    }
    
    ~INotify() {
        for(int i = 0; i < watches.GetCount(); i++) {
            inotify_rm_watch(fd, watches[i]);
        }
        
        LOG("inotify closed");
        close(fd);
    }
    
    Event<String> FileCreated;
    Event<String> FileDeleted;
    Event<String> FileMovedFrom;
    Event<String> FileMovedTo;
    
    Event<String> DirCreated;
    Event<String> DirDeleted;
    Event<String> DirMovedFrom;
    Event<String> DirMovedTo;
};

void IdeBackgroundThread()
{
    StdLogSetup(LOG_COUT);
    VectorMap<String, String> file;
    Index<String> dir;
    Index<String> filei;
    
    for(FindFile ff(ConfigFile("*.var")); ff && !Thread::IsShutdownThreads(); ff.Next()) {
        VectorMap<String, String> var;
        LoadVarFile(ff.GetPath(), var);
        for(String d : Split(var.Get("UPP", ""), ';'))
            dir.FindAdd(NormalizePath(d));
        Sleep(0);
    }
    
    INotify notify;
    notify.FileCreated   = [&](String name) { LOG(Format("File Created: %s", name));   filei.Add(name);       };
    notify.FileDeleted   = [&](String name) { LOG(Format("File Deleted: %s", name));   filei.RemoveKey(name); };
    notify.FileMovedFrom = [&](String name) { LOG(Format("File MovedFrom: %s", name)); filei.RemoveKey(name); };
    notify.FileMovedTo   = [&](String name) { LOG(Format("File MovedTo: %s", name));   filei.Add(name);       };
    notify.DirCreated    = [&](String name) { LOG(Format("Dir Created: %s", name));    dir.Add(name);         notify.AddWatchRecursive(name);    };
    notify.DirDeleted    = [&](String name) { LOG(Format("Dir Deleted: %s", name));    dir.RemoveKey(name);   notify.RemoveWatch(name); };
    notify.DirMovedFrom  = [&](String name) { LOG(Format("Dir MovedFrom: %s", name));  dir.RemoveKey(name);   notify.RemoveWatch(name); };
    notify.DirMovedTo    = [&](String name) { LOG(Format("Dir MovedTo: %s", name));    dir.Add(name);         notify.AddWatchRecursive(name);    };
    
    LOG(dir);
    
    for(String d : dir) {
        GatherAllFiles(d, filei, file);
        notify.AddWatch(d);
    }
    
    for(;;) {
        notify.Run();
        Sleep(100);
    }
}

CONSOLE_APP_MAIN {
    auto configFile = ConfigFile("*.var");
    
    LOG(ConfigFile("*.var"));
    IdeBackgroundThread();
}


I copied .var files over to the config directory for this project.
 
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Read Message
Previous Topic: TheIde UI look/feel/Style redesign
Next Topic: Navigator window - gone?
Goto Forum:
  


Current Time: Sat Jun 08 19:01:29 CEST 2024

Total time taken to generate the page: 0.02977 seconds