{"id":76,"date":"2009-03-03T17:38:57","date_gmt":"2009-03-03T16:38:57","guid":{"rendered":"http:\/\/netrix.org.pl\/index.php\/2009\/03\/03\/automatichandle-ciag-dalszy\/"},"modified":"2011-02-12T02:26:05","modified_gmt":"2011-02-12T01:26:05","slug":"automatichandle-ciag-dalszy","status":"publish","type":"post","link":"https:\/\/netrix.org.pl\/index.php\/2009\/03\/03\/automatichandle-ciag-dalszy\/","title":{"rendered":"AutomaticHandle ci\u0105g dalszy"},"content":{"rendered":"<p>Jak si\u0119 okazuje nic nie jest na pocz\u0105tku idealne. Dzi\u0119ki uwagom Revo uda\u0142o mi si\u0119 usprawni\u0107 szablon automatycznych uchwyt\u00f3w. Revo poradzi\u0142 mi dodanie dodatkowego wska\u017anika na licznik odwo\u0142a\u0144 do danego zasobu. Dzi\u0119ki temu mo\u017cliwe by\u0142o usuni\u0119cie jednej funkcji wirtualnej, a druga zosta\u0142a sprowadzona do roli sprz\u0105taczki, kt\u00f3ra zostaje wywo\u0142ana tylko w momencie, gdy licznik osi\u0105ga warto\u015b\u0107 0. Dodatkowo doda\u0142em sprawdzenie czy uchwyt nie jest zerowy przed odwo\u0142aniem si\u0119 do wska\u017anik\u00f3w.<\/p>\n<p>Poni\u017cej znajduj\u0119 si\u0119 kod poprawionej klasy szablonowej AutomaticHandle:<\/p>\n<pre lang=\"cpp\">\r\ntypedef unsigned int Dword;\r\n\r\ntemplate< typename TAG>\r\nclass AutomaticHandle\r\n{\r\npublic:\r\n\t\/\/ Podstawowy konstruktor\r\n\tAutomaticHandle(NLib::Dword handle, MHandleMgr* manager, NLib::Dword* resCounter) : m_handle(handle), m_manager(manager), m_resCounter(resCounter)\r\n\t{ if(m_handle) ++(*m_resCounter); }\r\n\t\/\/ Konstruktor kopiuj\u0105cy\r\n\tAutomaticHandle(const AutomaticHandle& src) : m_manager(src.m_manager), m_handle(src.m_handle), m_resCounter(src.m_resCounter)\r\n\t{ if(m_handle) ++(*m_resCounter); }\r\n\t\/\/ Destruktor\r\n\t~AutomaticHandle()\r\n\t{\r\n\t\tif(m_handle)\r\n\t\t{ if(!(--(*m_resCounter))) m_manager->ReleaseResource(m_handle); }\r\n\t}\r\n\t\/\/ Operator przypisania\r\n\tconst AutomaticHandle& operator =(const AutomaticHandle& src)\r\n\t{\r\n\t\tif(m_handle)\r\n\t\t{ if(!(--(*m_resCounter))) m_manager->ReleaseResource(m_handle); }\r\n\t\tm_handle = src.m_handle;\r\n\t\tif(m_handle) ++(*(m_resCounter = src.m_resCounter));\r\n\t\treturn src;\r\n\t}\r\n\t\/\/ Operator r\u00f3wno\u015bci\r\n\tbool operator ==(const AutomaticHandle& src)\r\n\t{ return m_handle == src.m_handle; }\r\n\t\/\/ Operator r\u00f3\u017cno\u015bci\r\n\tbool operator !=(const AutomaticHandle& src)\r\n\t{ return m_handle != src.m_handle; }\r\n\t\/\/ Operator Dword\r\n\toperator NLib::Dword() const\r\n\t{ return m_handle; }\r\n\t\/\/ Operator bool\r\n\toperator bool() const\r\n\t{ return !!m_handle; }\r\n\r\nprivate:\r\n\t\/\/ Uchwyt\r\n\tNLib::Dword m_handle;\r\n\t\/\/ Wska\u017anik do managera\r\n\tMHandleMgr* m_manager;\r\n\t\/\/ Wska\u017anik do licznika zasobu\r\n\tNLib::Dword* m_resCounter;\r\n};\r\n<\/pre>\n<p>Kolejn\u0105 klas\u0105 jest AutoHandleMgr, czyli klasa implementuj\u0105ca obs\u0142ug\u0119 automatycznych uchwyt\u00f3w. Aktualnie tylko trzy funkcje s\u0105 dost\u0119pne klasie pochodnej, w tym jedna dla uchwyt\u00f3w. Klasa ta posiada jedn\u0105 funkcj\u0119 abstrakcyjn\u0105, w kt\u00f3rej po zdefiniowaniu w klasie pochodnej nale\u017cy usuwa\u0107 odpowiednie zasoby zgodnie z przekazanym indeksem.<\/p>\n<p>Oto jej definicja:<\/p>\n<pre lang=\"cpp\">\r\ntypedef unsigned int Dword;\r\n\r\nclass AutoHandleMgr\r\n{\r\n\t\/\/ Unia do wyci\u0105gania informacji z uchwytu\r\n\tenum\r\n\t{\r\n\t\t\/\/ Rozmiary p\u00f3l\r\n\t\tMAX_BITS_INDEX = sizeof(NLib::Dword) * 4,\r\n\t\tMAX_BITS_MAGIC = sizeof(NLib::Dword) * 4,\r\n\t\t\/\/ Maksymalne warto\u015bci p\u00f3l\r\n\t\tMAX_INDEX = (1 << MAX_BITS_INDEX) - 1,\r\n\t\tMAX_MAGIC = (1 << MAX_BITS_MAGIC) - 1\r\n\t};\r\n\r\npublic:\r\n\t\/\/ Funkcja do zwracania uchwytu\r\n\tvoid ReleaseResource(NLib::Dword handle)\r\n\t{\r\n\t\tNAssert(GetIndex(handle) < m_magicValues.size(), \"Wrong Handle\");\r\n\t\tNAssert(CheckMagic(handle), \"Wrong handle\");\r\n\t\tDeleteHandleAt(GetIndex(handle));\r\n\t\tReleaseResourceByIndex(GetIndex(handle));\r\n\t}\r\n\r\nprotected:\r\n\t\/\/ Funkcja tworzy nowy uchwyt i go zwraca\r\n\t\/\/ Index zawarty w uchwycie odpowiada indeksowi w tablicy z danymi\r\n\t\/\/ w odziedziczonej klasie\r\n\tNLib::Dword CreateNewHandle()\r\n\t{\r\n\t\tNLib::Dword handle;\r\n\t\tstatic NLib::Dword s_autoMagic = 0;\r\n\t\tif(++s_autoMagic > MAX_MAGIC) s_autoMagic = 1;\t\/\/ 0 oznacza pusty uchwyt\r\n\t\t\/\/ Je\u017celi nie ma wolnych miejsc to tworze nowy index\r\n\t\tif(m_freeSlots.empty())\r\n\t\t{\r\n\t\t\thandle = m_magicValues.size() << (MAX_BITS_INDEX - 1);\r\n\t\t\tm_magicValues.push_back(s_autoMagic);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\thandle = m_freeSlots.back() << (MAX_BITS_INDEX - 1);\r\n\t\t\tm_magicValues[m_freeSlots.back()] = s_autoMagic;\r\n\t\t\tm_freeSlots.pop_back();\r\n\t\t}\r\n\t\thandle |= s_autoMagic;\r\n\t\treturn handle;\r\n\t}\r\n\t\/\/ Funkcja zwraca index\r\n\tNLib::Dword GetIndex(NLib::Dword handle)\r\n\t{ return (handle >> (MAX_BITS_INDEX - 1)) & MAX_INDEX; }\r\n\r\nprivate:\r\n\t\/\/ Funkcja kasuje wskazany uchwyt\r\n\tvoid DeleteHandleAt(NLib::Dword index)\r\n\t{\tm_freeSlots.push_back(index);\r\n\t\tm_magicValues[index] = 0; }\r\n\t\/\/ Funkcja zwraca cz\u0119\u015b\u0107 magiczn\u0105\r\n\tNLib::Dword GetMagic(NLib::Dword handle)\r\n\t{ return handle & MAX_MAGIC; }\r\n\t\/\/ Funkcja sprawdzaj\u0105ca warto\u015bc magic\r\n\tbool CheckMagic(NLib::Dword handle)\r\n\t{\tNAssert(GetIndex(handle) < m_magicValues.size(), \"Wrong Handle\");\r\n\t\treturn GetMagic(handle) == m_magicValues[GetIndex(handle)]; }\r\n\r\nprivate:\r\n\t\/\/ Funkcja dekrementuj\u0105ca licznik w zasobach\r\n\tvirtual void ReleaseResourceByIndex(NLib::Dword index) = 0;\r\n\r\nprivate:\r\n\t\/\/ Vector zawieraj\u0105cy magiczne warto\u015bci\r\n\tstd::vector m_magicValues;\r\n\t\/\/ Vector zawieraj\u0105cy indeksy z wolnymi miejscami\r\n\tstd::vector m_freeSlots;\r\n};\r\n<\/pre>\n<p>W przypadku tego menad\u017cera uchwyty musz\u0105 by\u0107 usuni\u0119te przed nim, inaczej pojawi\u0105 si\u0119 b\u0142\u0119dy z dost\u0119pem do pami\u0119ci.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Jak si\u0119 okazuje nic nie jest na pocz\u0105tku idealne. Dzi\u0119ki uwagom Revo uda\u0142o mi si\u0119 usprawni\u0107 szablon automatycznych uchwyt\u00f3w. Revo poradzi\u0142 mi dodanie dodatkowego wska\u017anika na licznik odwo\u0142a\u0144 do danego zasobu. Dzi\u0119ki temu mo\u017cliwe by\u0142o usuni\u0119cie jednej funkcji wirtualnej, a druga zosta\u0142a sprowadzona do roli sprz\u0105taczki, kt\u00f3ra zostaje wywo\u0142ana tylko w momencie, gdy licznik osi\u0105ga [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[12],"tags":[88,179,20],"_links":{"self":[{"href":"https:\/\/netrix.org.pl\/index.php\/wp-json\/wp\/v2\/posts\/76"}],"collection":[{"href":"https:\/\/netrix.org.pl\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/netrix.org.pl\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/netrix.org.pl\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/netrix.org.pl\/index.php\/wp-json\/wp\/v2\/comments?post=76"}],"version-history":[{"count":2,"href":"https:\/\/netrix.org.pl\/index.php\/wp-json\/wp\/v2\/posts\/76\/revisions"}],"predecessor-version":[{"id":799,"href":"https:\/\/netrix.org.pl\/index.php\/wp-json\/wp\/v2\/posts\/76\/revisions\/799"}],"wp:attachment":[{"href":"https:\/\/netrix.org.pl\/index.php\/wp-json\/wp\/v2\/media?parent=76"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/netrix.org.pl\/index.php\/wp-json\/wp\/v2\/categories?post=76"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/netrix.org.pl\/index.php\/wp-json\/wp\/v2\/tags?post=76"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}