Boost.Coroutine

Discussion in 'С/С++, C#, Rust, Swift, Go, Java, Perl, Ruby' started by greki_hoy, 27 Jul 2013.

  1. greki_hoy

    greki_hoy Member

    Joined:
    4 Mar 2010
    Messages:
    326
    Likes Received:
    57
    Reputations:
    41
    Всем привет

    пример демонстрирует применение сопрограмм (англ. coroutine) для "выправления" рекурсивного алгоритма...

    в качестве алгоритма используется рекурсивный поиск файлов...

    ну и покажу сразу примеры того что в итоге получилось... а вернее как этим пользоваться...

    например чтоб найти все файлы в c:\ и вложенных директориях надо задать маску *.*

    Code:
    int main()
    {
    	FileGenerator obj("c:\\*.*");
    
    	while (obj.hasNext())
    	{
    		printf("%s\n", obj.get());
    	}
    }
    
    если надо найти файлы только с расширением txt то тогда так

    Code:
    int main()
    {
    	FileGenerator obj("c:\\*.txt");
    
    	while (obj.hasNext())
    	{
    		printf("%s\n", obj.get());
    	}
    }
    
    второй параметр у FileGenerator определяет надо ли искать во вложенных директорих по умолчанию он ищет во всех вложенных директориях

    собственно реализация

    Code:
    
    #include <stdio.h>
    #include <tchar.h>
    #include <windows.h>
    #include <shlwapi.h>
    #include <boost/coroutine/all.hpp>
    #include <boost/bind.hpp>
    #include <boost/scope_exit.hpp>
    
    struct FileGenerator
    {
    	bool skip;
    
    	typedef boost::coroutines::coroutine<PCTSTR()> coro_t;
    
    	coro_t coro;
    
    	FileGenerator(PCTSTR path, BOOL bInnerFolders = TRUE)
    	{
    		skip = true;
    		start_coroutine(path, bInnerFolders);
    	}
    
    	void coroutine(coro_t::caller_type& yield, PCTSTR _path, BOOL bInnerFolders)
    	{
    		TCHAR path[MAX_PATH * 2];
    		TCHAR filename[_MAX_EXT];
    
    		if (PathSearchAndQualify(_path, path, _countof(path)))
    		{
    			LPCTSTR q = PathFindFileName(path);
    
    			if (q != path)
    			{
    				lstrcpyn(filename, q, _countof(filename));
    
    				PathRemoveFileSpec(path);
    
    				DoSearch(path, filename, bInnerFolders, yield);
    			}
    		}
    	}
    
    	void start_coroutine(PCTSTR path, BOOL bInnerFolders)
    	{ 
    		coro = coro_t(boost::bind(&FileGenerator::coroutine, this, _1, path, bInnerFolders));
    	}
    
    	bool hasNext()
    	{
    		skip ? skip = false : coro();
    
    		return coro;
    	}
    
    	PCTSTR get()
    	{
    		return coro.get();
    	}
    
    	VOID DoSearch(LPTSTR path, LPCTSTR filename, 
    		BOOL bInnerFolders, coro_t::caller_type& yield)
    	{
    		HANDLE hSearch;
    		WIN32_FIND_DATA wfd;
    
    		PathAddBackslash(path);
    		PathCombine(path, path, _T("*.*"));
    
    		LPTSTR q = PathFindFileName(path);
    
    
    		if(bInnerFolders)
    		{
    			hSearch = FindFirstFile(path, &wfd);
    
    			if (INVALID_HANDLE_VALUE != hSearch)
    			{
    				BOOST_SCOPE_EXIT_ALL(&)
    				{
    					FindClose(hSearch);
    				};
    
    				do
    				{
    					if (*wfd.cFileName == _T('.'))
    						continue;
    
    					if (FILE_ATTRIBUTE_DIRECTORY & wfd.dwFileAttributes) 
    					{
    						lstrcpy(q, wfd.cFileName);
    						DoSearch(path, filename, bInnerFolders, yield);
    					}
    
    				} while (FindNextFile(hSearch, &wfd));
    			}
    		}
    
    		lstrcpy(q, filename);
    
    		hSearch = FindFirstFile(path, &wfd);
    
    		if (INVALID_HANDLE_VALUE != hSearch)
    		{
    			BOOST_SCOPE_EXIT_ALL(&)
    			{
    				FindClose(hSearch);
    			};
    
    			do
    			{
    				if (!(FILE_ATTRIBUTE_DIRECTORY & wfd.dwFileAttributes))
    				{
    					lstrcpy(q, wfd.cFileName);
    
    					yield(path);
    				}
    
    			} while (FindNextFile(hSearch, &wfd)); 
    		}
    	}
    };
    
    
    
    
    
     
    #1 greki_hoy, 27 Jul 2013
    Last edited: 27 Jul 2013