<div dir="ltr"><br><div class="gmail_extra"><br><br><div class="gmail_quote">2014-06-20 17:09 GMT+08:00 Michal Privoznik <span dir="ltr"><<a href="mailto:mprivozn@redhat.com" target="_blank">mprivozn@redhat.com</a>></span>:<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div class="">On 17.06.2014 13:06, Taowei wrote:<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
Define the vboxUniformedAPI struct to handle version conflicts.<br>
The vboxInitialize is rewrited with the new mechanism. Other<br>
functions would be rewriting in the same way.<br>
</blockquote>
<br></div>
s/rewriting/rewritten/<div class=""><br>
<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<br>
Here, I still use template to generate functions in vboxUniformedAPI.<br>
Though, these functions may change between different versions, but<br>
not for every version. Using template could decrease the duplicated code.<br>
<br>
For every new feature added by vbox, a flag would indicate whether this<br>
feature is supported in current version. Calling for an unsupported<br>
feature would lead to a VIR_WARN.<br>
<br>
---<br>
  src/vbox/vbox_tmpl.c |   84 ++++++++++++++++++++++++++++++<u></u>++++++--------------<br>
  1 file changed, 61 insertions(+), 23 deletions(-)<br>
<br>
diff --git a/src/vbox/vbox_tmpl.c b/src/vbox/vbox_tmpl.c<br>
index 1ed2729..4625805 100644<br>
--- a/src/vbox/vbox_tmpl.c<br>
+++ b/src/vbox/vbox_tmpl.c<br>
@@ -826,6 +826,65 @@ static PRUnichar *PRUnicharFromInt(int n) {<br>
<br>
  #endif /* !(VBOX_API_VERSION == 2002000) */<br>
<br>
+/* Begin of vboxUniformedAPI */<br>
+<br>
+#define UNUSED(expr) do { (void)(expr); } while (0)<br>
</blockquote>
<br></div>
We have ATTRIBUTE_UNUSED which can serve this purpose. Or ignore_value() depending on the use case.<div class=""><br>
<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
+<br>
+static void _pfnComInitialize(<u></u>vboxGlobalData *data)<br>
+{<br>
+#if VBOX_XPCOMC_VERSION == 0x00010000U<br>
+    data->pFuncs-><u></u>pfnComInitialize(&data-><u></u>vboxObj, &data->vboxSession);<br>
+#else  /* !(VBOX_XPCOMC_VERSION == 0x00010000U) */<br>
+    data->pFuncs-><u></u>pfnComInitialize(IVIRTUALBOX_<u></u>IID_STR, &data->vboxObj, ISESSION_IID_STR, &data->vboxSession);<br>
+#endif /* !(VBOX_XPCOMC_VERSION == 0x00010000U) */<br>
+}<br>
+<br>
+#if (VBOX_XPCOMC_VERSION == 0x00010000U) || (VBOX_API_VERSION == 2002000)<br>
+    #define FWATCH_NEED_INITICAL 0<br>
+#else /* (VBOX_XPCOMC_VERSION != 0x00010000U && VBOX_API_VERSION != 2002000) */<br>
+    #define FWATCH_NEED_INITICAL 1<br>
+#endif /* (VBOX_XPCOMC_VERSION != 0x00010000U && VBOX_API_VERSION != 2002000) */<br>
+<br>
+static int _initicalFWatch(vboxGlobalData *data)<br>
</blockquote>
<br></div>
so this would be:<br>
static int<br>
_initicalFWatch(vboxGlobalData *data ATTRIBUTE_UNUSED)<br>
{ ... }<br>
<br>
even though the @data might be used later (depending on VBOX version).<div class=""><br>
<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
+{<br>
+#if FWATCH_NEED_INITICAL == 0<br>
</blockquote>
<br></div>
What's the reason for not having:<br>
<br>
#ifdef VBOX_XPCOMC_VERSION .. || VBOX_API_VERSION ..<br>
<br>
#else<br>
<br>
#endinf<br>
<br>
I don't think I see why you need to invent this new preprocessor symbol.<div class=""><br></div></blockquote><div> </div><div><div>The fWatchNeedInitial is a flag that indicates whether we need to initial fdWatch and vboxQueue in vboxGlobalData. VBox2.2 has no event call back, so we don't need to call it.<div>
I expect that others would know whether they need to initialize the fdWatch, so the flag and the fWatchNeedInitial is introduced.</div></div><div><br></div><div>Do you mean just use VBOX_XPCOMC_VERSION and VBOX_API_VERSION to check directly?</div>
</div><div><br></div><div>I will modify the next codes with your advise. <br></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<div class="">
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
+    /* No event queue functionality in 2.2.* as of now */<br>
+    UNUSED(data);<br>
+    VIR_WARN("There is no fWatch initical in current version");<br>
+#else /* FWATCH_NEED_INITICAL != 0 */<br>
+    /* Initial the fWatch needed for Event Callbacks */<br>
+    data->fdWatch = -1;<br>
+    data->pFuncs-><u></u>pfnGetEventQueue(&data-><u></u>vboxQueue);<br>
+    if (data->vboxQueue == NULL) {<br>
+        virReportError(VIR_ERR_<u></u>INTERNAL_ERROR, "%s",<br>
+                       _("nsIEventQueue object is null"));<br>
+        return -1;<br>
+    }<br>
+#endif /* FWATCH_NEED_INITICAL != 0 */<br>
+    return 0;<br>
+}<br>
+<br>
+typedef struct {<br>
+    /* vbox API version */<br>
+    uint32_t uVersion;<br>
+    /* vbox APIs */<br>
+    void  (*pfnComInitialize)(<u></u>vboxGlobalData *data);<br>
+    int (*initicalFWatch)(<u></u>vboxGlobalData *data);<br>
+    /* vbox API features */<br>
+    unsigned fWatchNeedInitical : 1;<br>
</blockquote>
<br></div>
s /unsigned .. :1/bool/<br>
<br>
And what does Initical stands for anyway?<div class=""><div class="h5"><br>
<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
+} vboxUniformedAPI;<br>
+<br>
+static vboxUniformedAPI vboxAPI = {<br>
+    .uVersion = VBOX_API_VERSION,<br>
+    .pfnComInitialize = _pfnComInitialize,<br>
+    .initicalFWatch = _initicalFWatch,<br>
+    .fWatchNeedInitical = FWATCH_NEED_INITICAL,<br>
+};<br>
+<br>
+static vboxUniformedAPI *pVboxAPI = &vboxAPI;<br>
+<br>
+/* End of vboxUniformedAPI and Begin of common codes */<br>
+<br>
  static PRUnichar *<br>
  vboxSocketFormatAddrUtf16(<u></u>vboxGlobalData *data, virSocketAddrPtr addr)<br>
  {<br>
@@ -923,31 +982,10 @@ vboxInitialize(vboxGlobalData *data)<br>
      if (data->pFuncs == NULL)<br>
          goto cleanup;<br>
<br>
-#if VBOX_XPCOMC_VERSION == 0x00010000U<br>
-    data->pFuncs-><u></u>pfnComInitialize(&data-><u></u>vboxObj, &data->vboxSession);<br>
-#else  /* !(VBOX_XPCOMC_VERSION == 0x00010000U) */<br>
-    data->pFuncs-><u></u>pfnComInitialize(IVIRTUALBOX_<u></u>IID_STR, &data->vboxObj,<br>
-                               ISESSION_IID_STR, &data->vboxSession);<br>
-<br>
-# if VBOX_API_VERSION == 2002000<br>
-<br>
-    /* No event queue functionality in 2.2.* as of now */<br>
-<br>
-# else  /* !(VBOX_API_VERSION == 2002000) */<br>
+    pVboxAPI->pfnComInitialize(<u></u>data);<br>
<br>
-    /* Initial the fWatch needed for Event Callbacks */<br>
-    data->fdWatch = -1;<br>
-<br>
-    data->pFuncs-><u></u>pfnGetEventQueue(&data-><u></u>vboxQueue);<br>
-<br>
-    if (data->vboxQueue == NULL) {<br>
-        virReportError(VIR_ERR_<u></u>INTERNAL_ERROR, "%s",<br>
-                       _("nsIEventQueue object is null"));<br>
+    if (pVboxAPI->fWatchNeedInitical && pVboxAPI->initicalFWatch(data) != 0)<br>
          goto cleanup;<br>
-    }<br>
-<br>
-# endif /* !(VBOX_API_VERSION == 2002000) */<br>
-#endif /* !(VBOX_XPCOMC_VERSION == 0x00010000U) */<br>
<br>
      if (data->vboxObj == NULL) {<br>
          virReportError(VIR_ERR_<u></u>INTERNAL_ERROR, "%s",<br>
<br>
</blockquote>
<br></div></div><span class=""><font color="#888888">
Michal<br>
</font></span></blockquote></div><br></div></div>