gtk-gnome-intro.html

来自「linux下gnome编程」· HTML 代码 · 共 999 行 · 第 1/3 页

HTML
999
字号
CLASS="PROGRAMLISTING">guint (*GHashFunc) (gconstpointer key);gint (*GCompareFunc) (gconstpointer a, gconstpointer b);        </PRE></TD></TR></TABLE><P>          As we've seen, GLib's implementation of hash tables is very          generic and allows you to declare your own hash and          comparison functions. If you are writing your own hashing          functions, you should do your best to avoid creating          duplicate hash values, in order to keep the buckets from          filling up. For example, if your hashing algorithm used          only the first four characters of a string-based key, any          lookups of keys that started with the same four characters          would result in a bucket collision, which would degrade          performance of the hash table. Thus a lookup of the key          "mythic" would return the same hash value as a lookup of          "mythological" and "mythos." Each time you performed a          lookup on one of these keys, GLib would have to sift through          the linked list of "myth" keys in that bucket.        </P><P>          To save you the trouble of creating algorithms for the most          common types of keys, GLib supplies a handful of prespun          hashing functions. You must specify the hashing function          when you create the hash table, and you cannot change it          later. The GHashTable structure holds the data used by the          hash table; you should always use the g_hash_table_*          functions to access it. The GHashTable structure is          classified as opaque, so you should never access its fields          directly.        </P><P>          Hash tables are neat and pretty efficient, but they do have          their limitations.  Even though the keys are reduced to          integer values, the hash table must cycle through them          sequentially when performing lookups. The contents are not          sorted, and no guarantees can be made regarding the order of          the elements.  Lookup times will depend on the hashing          function you use, the number of hash collisions in your data          set, and the order in which you happened to add the          elements.        </P><P>          The balanced binary tree (GTree) is in a sense a specialized          version of a hash table, with its own peculiar quirks. While          the hash table is fundamentally an optimized list container,          the binary tree is a sorted hierarchical container.  Each          time you add an element to the binary tree, the tree adjusts          itself to make the next lookup operation as efficient as          possible. Each node on the tree can have at most two          branches (or nodes). Each subnode can in turn have two          branches (nodes) of its own, and so on. The tree struggles          to keep both sides of every branch balanced. If you add          nodes to the left side of a tree, the tree will shuffle          things around so that both sides contain a similar number of          nodes.        </P><P>          Thus while the hash table is optimized for faster single key          comparisons but may end up traversing an inefficient number          of elements for each lookup, the binary tree is optimized          for the fewest number of traversals possible. You can          customize the way in which the binary tree distributes its          nodes by changing the sorting algorithm.        </P><P>          Although, technically speaking, binary trees have a          hierarchical structure, you as a programmer don't explicitly          benefit from it. Your lookups are faster, and you have more          sorting and traversal options, but you don't really have di-          rect control over where your data ends up in the          tree. Inserting a new element into a binary tree may trigger          a massive shuffling of branches as the tree struggles to          rebalance itself. Parents may switch positions with children          or move farther down the hierarchy. You can depend on the          fact that, for example, a certain element will always remain          on the left side of another element, but not how far to the          left.        </P><P>          GNode, GLib's n-ary tree container, gives you this critical          control. If you put a GNode at a certain place in the tree,          it will stay there until you move it.  Furthermore, any          element in a GNode tree can have a potentially unlimited          number of children or siblings (although each element should          only have one parent). In a sense, the GNode is similar to a          two-dimensional doubly linked list, in which you can iterate          from sibling to sibling and from parent to child (see Figure          2.3).        </P><DIVCLASS="FIGURE"><ANAME="AEN114"></A><P><B>Figure 2-3. Structure of an N-ary Tree</B></P><DIVCLASS="MEDIAOBJECT"><P><IMGSRC="figures/2f3.png"></IMG></P></DIV></DIV><P>          We've covered a lot of ground in this section without          showing a single scrap of useful container code. You may not          have learned much about how to write code for GLib's many          containers, but hopefully you now have a better idea of how          they work. This should make it much easier to understand the          containers' APIs. The online GLib documentation covers all          of this in much greater detail.        </P></DIV><DIVCLASS="SECT2"><H2CLASS="SECT2"><ANAME="AEN120">Other Toys</A></H2><P>          GLib isn't just a reservoir for data containers and          portability wrappers. It also harbors a surprising range of          useful tools and utilities. Not only does it provide generic          abstractions for threads, dynamically loaded modules, and          input/output handling, but it also contains such gems as a          full-featured event loop (used extensively by GTK+) and a          lexical scanner for parsing through text streams.        </P><P>          Thread handling is a very complicated affair, far beyond the          scope of this book. We'll touch on it only lightly          here. GLib's thread implementation is by no means          comprehensive, or particularly advanced; in fact, it is only          just enough to make GLib thread-safe. It covers the basics          in a clear, simple manner, providing thread          synchronization through mutexes (GMutex and GStaticMutex)          and thread-local data (GPrivate and GStaticPrivate), al-          though at this time it does not contain functions to create          and destroy the threads. You'll have to use your operating          system's thread API directly for that.  GLib's GThread          implementation resides in a standalone library, libgthread,          and is more or less just a wrapper around the native thread          library-for example, libpthread.        </P><P>          GLib's GModule interface provides a portable wrapper around          the dynamic module-loading APIs of most modern operating          systems, including Linux, Solaris, IRIX, HP/UX, and even          Microsoft Windows (as DLL, Dynamic Link Library,          files). You can use it to load in libraries at runtime-for          example, as part of a plug-in architecture, like the          countless graphics filters in the GIMP drawing          application. Using the GModule functions, you can load up a          dynamic module, search for specific functions inside it,          invoke those functions, and then close the module. GModule          insulates you from the often vast differences in dynamic          loading between platforms and leads to more portable          code. Like GThread, the GModule implementation resides in          its own library, libgmodule.        </P><P>          GLib also contains a handful of dynamic memory management          functions, in the form of wrappers around the standard C          memory functions. You can use g_new( ) and g_malloc( ) to          freshly allocate memory, g_new0( ) and g_malloc0( ) to          allocate memory initialized to zeros, and g_renew( ) and          g_realloc( ) to reallocate existing memory to a different          size. The g_free( ) function cleans up the memory,          regardless of which GLib function you used to allocate          it. The optional functions g_mem_profile( ) and g_mem_check(          ) provide you with feedback on the currently allocated          memory, although since these functions introduce a          performance penalty, you'll have to compile your version of          GLib with the configure script options --enable-mem-profile          and --enable-mem-check to use them.        </P><P>          If you plan on allocating and freeing lots of small chunks          of memory, you might want to look into GLib's block memory          support. GMemChunk allocates a single chunk of memory to          store many smaller, contiguous objects. It handles the          memory management for you, keeping track of which chunks are          in use and which chunks have been freed. When you request a          new chunk of memory, GMemChunk gives you a pointer to an          existing slice of its larger block, rather than allocating          new memory with the more costly call to g_malloc( ). GLib          uses GMemChunk internally, for its linked list and GNode          data containers.        </P><P>          The GIOChannel interface is a wrapper around standard UNIX          files, sockets, and pipes that brings consistency and          portability to the methods you use to handle these file          descriptors. GIOChannel also helps integrate input/output          polling and callbacks into GLib's event loop. This feature          will come in handy if your application needs to periodically          check on a socket or pipe connection without blocking each          time (which would interfere with your application's          repainting and responsiveness), or monitor a file for          changes. You'll have to create the file descriptor yourself          (unless you're using stdin, stdout, or stderr), but once you          wrap it in a GIOChannel, you can use GLib to wire it into          the event loop for callback notifications, to read and write          from it, and to close it when you're done. GIOChannel also          supports reference counting, in case you need to share a          channel with more than one object.        </P><P>          The GMainLoop event loop is the heartbeat of most GTK+ and          GNOME applications. The event loop cycles continuously          through its iterations, nudging all the various hooks and          event streams you've installed into it. The event loop is          like a many-armed conductor sitting at the center of your          application, letting you know when important things          happen. You can set up polling events based on file          descriptors (e.g., with GIOChannel), timers to synthesize          periodic events, and even generic event sources (like the          GDK event queue).  You can also prioritize your event          sources so that, for example, a certain socket event takes          priority over certain timer events. If you have any          low-priority maintenance routines that you want to run in          the background, you can install them as idle handlers in the          event loop. When the event loop runs out of events, it will          spend its time running the idle functions. GMainLoop is ex-          tremely versatile and can be used in virtually any          event-driven software. It was originally part of GTK+, but          later it was abstracted and pulled into GLib to make it          available to applications outside of GTK+.        </P><P>          Moving along, the lexical scanner, GScanner, is a generic,          configurable text-parsing tool. It's good for reading in          configuration files, which is exactly what GTK+ uses it          for. GTK+ reads in a text-based gtkrc file each time you          start up an application; the user can define the appearance          and behavior of GTK+ in the gtkrc file. GScanner recognizes          a wide assortment of common tokens, like curly braces,          numbers, characters, commas, and even various styles of          comments. You can also define custom symbols, or tokens, if          the basic set doesn't cover your needs. By tweaking the          contents of the GScannerConfig structure and passing it on          to GScanner, you can exert very fine control over which          tokens the lexical scanner will acknowledge and how it          reacts to different combinations of tokens. Once the          GScanner is set up, you can repeatedly call the          g_scanner_get_next_token ( ) function to grab tokens one at          a time until you're finished, or until you reach the end of          the file. GLib's lexical scanner is surprisingly powerful          for such a small, rarely used bit of code. The interface is          admittedly a little cryptic, and the documentation is a          bit thinner than it could be, but it's quite easy to use          once you grasp how it works. For a working example, take a          look at the file gtk+/gtk/gtkrc.c in the GTK+ source code          distribution.        </P><P>          Future versions of GTK+, starting with GTK+ 2.0, will          contain the GObject infrastructure, for managing          object-oriented systems. GObject is essentially the GTK+          object system ripped out of GTK+ and made available to          non-GTK+ applications, much as the GTK+ main loop was          extracted and put into GMainLoop.        </P></DIV></DIV></DIV><DIVCLASS="NAVFOOTER"><HRALIGN="LEFT"WIDTH="100%"><TABLEWIDTH="100%"BORDER="0"CELLPADDING="0"CELLSPACING="0"><TR><TDWIDTH="33%"ALIGN="left"VALIGN="top"><AHREF="acknowledgements.html">Prev</A></TD><TDWIDTH="34%"ALIGN="center"VALIGN="top"><AHREF="index.html">Home</A></TD><TDWIDTH="33%"ALIGN="right"VALIGN="top"><AHREF="gdk.html">Next</A></TD></TR><TR><TDWIDTH="33%"ALIGN="left"VALIGN="top">Acknowledgments</TD><TDWIDTH="34%"ALIGN="center"VALIGN="top">&nbsp;</TD><TDWIDTH="33%"ALIGN="right"VALIGN="top">GDK</TD></TR></TABLE></DIV></BODY></HTML>

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?